Hi! I’m having a problem making a worm-like attack for my game, similar to the worm in lethal company that comes up from the ground. I wanted to use a sort of simplified IK or verlet integration-esque system to position each segment after the other as it moves.
The problem is, with each iteration the result gets more and more chaotic until it devolves into a mess.
Video Example
Muted myself for privacy reasons, but what I said was:
“Each iteration gets off by a little bit until eventually it devolves into a mess.”
Here’s the current code, as well as a summary of what I’ve tried:
Code
My thought process:
- I started off with RunService, but I’m worried the behavior of RunService would mess something up, and a wait() loop works fine.
- I tried adding waits in between some stuff, concerned that the positions weren’t updating right away when the segment after it was sampling, but that doesn’t seem to be the problem. The waits helped but made it too laggy.
- I tried making it use :GetPropertyChangedSignal(“Position”) events for each segment’s parent. Same result.
Notes:
- It’s all anchored + can’t collide.
- The direction between two segments seems to only return NaN once, at the beginning of the script.
- The segments are parented to each other in the order they’re positioned it, so they’ll update in order. This also isn’t affecting the result, because without recursing, only the first one updates, as expected.
- I don’t want to use roblox physics, I want it all math based. Roblox physics are a mess to work with.
- Currently I think the issue is the positions it’s moving at a time is far too small to be precise from frame to frame, but I have no way of fixing this. This is also why I think the waits were helping, instead of giving it time to update, it was simply letting the positions it needed to move be bigger.
function recursiveUpdate(inst)
-- position and align
local newPos = inst.Parent.Position-inst.Parent.CFrame.LookVector*62
local newDir = (newPos-inst.Position).Unit
if newDir == newDir then -- check to make sure .Unit result isn't NaN
inst.CFrame = CFrame.lookAt(newPos,newPos+newDir)
-- recurse
for _,inst2 in ipairs(inst:GetChildren()) do
if inst2:IsA("MeshPart") and inst2.Name == "DuckWormBody" then
recursiveUpdate(inst2)
end
end
end
end
while task.wait() do
for _,inst in ipairs(script.Parent:GetChildren()) do
if inst:IsA("MeshPart") and inst.Name == "DuckWormBody" then
recursiveUpdate(inst)
end
end
end