Procedural animation thingy

Hey all I was just wondering if there was anything I can do to make the movement of the legs any smoother or faster? In the the video that they look fine when just walking normally but when it turns you can see the disconnect from the body and the leg.

[Local Script]
I have a heartbeat loop for the player input and calling the update function, not much else in here

runService.RenderStepped:Connect(function(dt)
	local mouseDelta = math.rad(userInput:GetMouseDelta().X) / 10
	mouseDelta = math.clamp(mouseDelta, -0.15, 0.15)
	origin.CFrame *= CFrame.Angles(0, -mouseDelta, 0)

	velocity.x = 0
	velocity.z = 0

	if (getKey(Enum.KeyCode.W)) then
		velocity.z = -SPEED
	elseif (getKey(Enum.KeyCode.S)) then
		velocity.z = SPEED
	end

	if (getKey(Enum.KeyCode.A)) then
		velocity.x = -SPEED
	elseif (getKey(Enum.KeyCode.D)) then
		velocity.x = SPEED
	end

	local direction = Vector3.new(velocity.x, 0, velocity.z).Unit
	if (direction ~= direction) then
		direction = Vector3.new(0, 0, 0)
	end
	
	origin.CFrame *= CFrame.new(direction * SPEED)

	for _, leg in pairs(legs) do
		leg.update()
	end
	
	IK.updateRoot(origin, legs, originalHeight)
end)

[Module Script]
Checks the distance between the current leg position and the fixed “default” position that moves with the body, calls moveTarget() if distance is greater than a threshold and leg is grounded

function this.update()
	updateFixedTarget()
	
	if ((pFixed.Position - target).Magnitude >= STEP_DISTANCE) and (this.isGrounded()) then
		moveTarget(pFixed.Position.Z - target.Z)
	end

This is the function that moves the target the legs are pointing to, using a quad bezier to give the movement some curvature

local function moveTarget(offset)
	for i = 0, 1, 0.1 do
		target = utils.quadBezier(
			i,
			target,
			target:Lerp(pFixed.Position, 0.5) + Vector3.new(0, 1, 0),
			pFixed.Position + Vector3.new(0, 0, offset / 2)
		)
		task.wait()
	end
end

Back to the update function, this is where it all actually happens. I basically make a right triangle between the legs and the target point. Then I use the side side side formula which is utils.SSS in here to get all the angles. From there, I just set the CFrames of the leg parts directly and that’s pretty much the main portion of how it works.

	local sideC = (target - shoulder.Position).Magnitude

    -- check if distance is too large, if it is then just point at the target
	if (sideC >= size.Z * #this.segments) then
		a.CFrame = CFrame.lookAt(shoulder.Position, target) * CFrame.new(0, 0, -sideA / 2)
		b.CFrame = a.CFrame * CFrame.new(0, 0, -sideB)
		return
	end
	
	local angleA = utils.SSS(sideB, sideC, sideA)
	local angleC = utils.SSS(sideA, sideB, sideC)

	a.CFrame = CFrame.lookAt(shoulder.Position, target)
				* CFrame.Angles(angleA, 0, 0)
				* CFrame.new(0, 0, -sideA / 2)

	b.CFrame = a.CFrame 
               * CFrame.new(0, 0, -sideA / 2) 
               * CFrame.Angles(angleC, math.rad(180), 0)
               * CFrame.new(0, 0, -sideB / 2)
end

I also feel that it’s worth mentioning that the loop seems to take a significant longer time when I am making drastic turns relative to just normal walking.
image
That is all and thank you

5 Likes

You should rig it instead of letting it follow the base of the spider. I’d say just add the joint property the parts of each limb closest to the base, maybe even add joints to the whole limb.

If you don’t want to go out the way to do extra things, then I’d just recommend updating how frequently it updates, as that factors to how noticeable the disconnecting problem is.

1 Like

Hey, sorry but could you elaborate a bit more? I’m not completely sure on what rigging is, from what I understand, is that adding bones in blender? If it is then I don’t know how that would help the issue

To be honest with you, no idea what you are trying to say here, sorry

3 Likes

moveTarget is the only provided snippet that contains yielding, so I assume that’s the culprit for the long wait times and ultimately the delayed movement of the limbs

What quad bezier module are you using?

3 Likes

Well, I put the function into a coroutine and that seemed to have completely eliminated the problem. Don’t know how I didn’t think of that lol but thank you for bringing it up.

I’m just using the function from the roblox wiki page on bezier curves

function quadBezier(t, p0, p1, p2)
	return (1 - t)^2 * p0 + 2 * (1 - t) * t * p1 + t^2 * p2
end
2 Likes

Personally I used a rig + IK control and it works very well. if you want i can give you more info about my system.

DM me justterror

btw i need to add hinge constraint to limits some movements of my spider but im not very good with that so if anyone knows how they work. can you help me ? my discord is justterror

1 Like