Procedural Animation

Hey everyone! Recently I’ve been interested in Procedural Animation and the process of making it in Roblox studio. Sadly, I have not seen many tutorials on it, so here we are!
In this Topic we’ll talk about what Procedural Animation is, it’s uses and how to add it to your Roblox game! Let’s begin.

What is Procedural Animation?


Procedural Animation is the process of automatically generating animations in real-time using code, allowing more diverse series of actions that would otherwise be very tedious to make using standard animations.

Procedural Animation can be used for particles, cloth, rigid body dynamics, and of course, character animation.

How to make Procedural Animation?


There are 2 known ways of making procedural character animations, the first is by using Raycasts, and the second one using simple points around the character to act like an “anchor” for the legs.

In this tutorial we will go for the second option since it’s much easier to make and has similar results to the Raycast version.

To make procedural character animations we will need something called Inverse Kinematics, it’s a complicated topic and I will not go over how it works or how to make it yourself. If you’re interested in that, consider reading this topic about Inverse Kinematics in Roblox Studio.

In this tutorial we will use a library made by robert_stevey to provide us with a simple R6 IK module that we will use. You can get it from here

Now we are all set! Let’s begin making some procedural animation!

Making Procedural Animation


In this tutorial we will make some very simple procedural walk animations for r6 rigs. Let’s begin!

First, make a new roblox game, add the IK module and insert a new rig. (It is recommended to put the module in ReplicatedStorage for server and client side access).

Next, we need to make 4 parts, 2 will be the “anchor” of the legs (where the legs will be attached), and 2 will be the final positions of the legs (the final positions of the walk cycle), we want our legs to reach in front of the character, so we will position them in front of the character.

Make sure that the leg anchors arent in the character model, we want those to fall behind and then smoothly move to the final leg positions.

In the end it should look something like this:

You can name the parts whatever you want, but make sure their names make sense.


Now, add a new script inside the dummy, name it something like “ProceduralAnimations” and open it.

First, we need to reference our module, we can require it with the require() function, it should look something like this:

local ik = require(game.ReplicatedStorage.R6IK)

Now that we have our ik module, let’s make our IK rig, we can do that using the function ik.New() and provide as a parameter the character model:

local rig = ik.New(script.Parent)

The rig variable provides us with one very important IK function that will attach our legs to the anchors.

Now, let’s make 4 variables that are equal to the 4 parts we made earlier, give them useful names like rightLegAnchor and LeftLegStep

Lets create a new function, name it something like LockToAnchor and make it lock our legs to the anchor parts we made:

function lockToAnchor()
	rig:LegIK("Right", rightLegTarget.Position)
	rig:LegIK("Left", leftLegTarget.Position)
end

Now, call the function and run the game, you should see the legs now be anchored to the 2 parts we made! But there’s one issue, if we move the anchor parts around the legs remain static, that’s because we only call our lockToAnchor function once, so the legs don’t update.

What we can do to solve this is move this function into a RunService.Stepped() function, so let’s do that really quick:

local RunService = game:GetService("RunService")

RunService.Stepped:Connect(function(_, dt)

	lockToAnchor()

end)

Now if we run the game we should see the legs update every time we move the anchors around, Nice!

Next, let’s make a Step() function that will smoothly move our leg anchors to the corresponding leg step point. We will use TweenService, but you can also use Lerp if you’re more comfortable with it. Make a TweenInfo variable and set its speed to something quick like 0.01, use whatever interpolations you want.

We will get as a parameter the leg we want to move (Right or Left) and make a corresponding tween for it:

local tweenService = game:GetService("TweenService")

function Step(legSide)
	local anchor, stepPart

	if legSide == "Right" then
		anchor = rightLegAnchor
		stepPart = rightLegStep
	else
		target = leftLegTarget
		stepPart = leftLegStep
	end

       local tweenInfo = TweenInfo.new(0.01, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut)

       local stepTween = tweenService:Create(anchor, tweenInfo, { Position = stepPart.Position })
       stepTween:Play()
end

Now if we call the Step() function and give it a side the corresponding anchor should move!
Let’s now make a “currentLeg” variable and edit the “Step” function to set it to the current leg moving and also add a “stepping” variable that will tell us if the character is stepping or not:

local currentLeg = "Right"
local stepping = false

function Step(legSide)
	if stepping then return end
	stepping = true


	local anchor, stepPart

	if legSide == "Right" then
		anchor = rightLegAnchor
		stepPart = rightLegStep
	else
		target = leftLegTarget
		stepPart = leftLegStep
	end

       local tweenInfo = TweenInfo.new(0.1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut)

       local stepTween = tweenService:Create(anchor, tweenInfo, { Position = stepPart.Position })
       stepTween:Play()

	stepTween.Completed:Once(function()
		stepping = false
		currentLeg = (legSide == "Right") and "Left" or "Right"
	end)
end

Next, we will need to check if the leg anchors are far enough from the leg step points, and if they are then call the Step() function on the corresponding leg. We will do this by creating a new function called handleStepping():

function handleStepping()
	if stepping then return end

	local rightDist = (rightLegAnchor.Position - rightLegStep.Position).Magnitude
	local leftDist = (leftLegAnchor.Position - leftLegStep.Position).Magnitude

	if currentLeg == "Right" and rightDist > 3 then
		Step("Right")
	elseif currentLeg == "Left" and leftDist > 3 then
		Step("Left")
	end
end

Now if we add the handleStepping function in the RunService.Stepped event the character should start “stepping” if you move him around!

There’s an issue though, both of the legs move at roughly the same time, which doesn’t make sense we can very easily fix that by just adding a small cooldown when the stepTween completes:

stepTween.Completed:Once(function()
		task.wait(0.15)
		stepping = false
		currentLeg = (legSide == "Right") and "Left" or "Right"
	end)

You can change this value if you want the legs to move faster or slower!

Now if we run the game the character should procedurally move it’s legs forward when moving. But there’s another issue (i promise it’s the last one and then we’re done), the legs only move forwards, if we move the character sideways or backwards the legs will still act like the character is moving forward, we can fix this by moving the leg step positions based on the direction the rig is moving in. Let’s add in our final function called updateStepPositions() and as a parameter get “dt” (delta time):

local root = script.Parent:WaitForChild("HumanoidRootPart")
local lastPos = nil
local moveDir = Vector3.new(0, 0, 1)
local stepWidth = 1 
local stepForward = 1

local function updateStepPositions(dt)
	local rootCFrame = root.CFrame
	local rootPos = root.Position

	if lastPos then
		local delta = rootPos - lastPos
		if delta.Magnitude > 0.05 then -
			moveDir = delta.Unit
		end
	end
	lastPos = rootPos

	-- build a CFrame facing the *movement* direction
	local moveCF = CFrame.lookAt(rootPos, rootPos + moveDir)

	-- offsets relative to that movement direction
	local rightOffset = Vector3.new(stepWidth / 2, -3, -stepForward)
	local leftOffset = Vector3.new(-stepWidth / 2, -3, -stepForward)

	-- move the step points using movement-facing CFrame
	local posInfo = TweenInfo.new(0.1, Enum.EasingStyle.Sine, Enum.EasingDirection.Out)

	local tweenRight = tweenService:Create(rightLegStep, posInfo, {Position = (moveCF * CFrame.new(rightOffset)).Position})
	local tweenLeft = tweenService:Create(leftLegStep, posInfo, {Position = (moveCF * CFrame.new(leftOffset)).Position})

	tweenRight:Play()
	tweenLeft:Play()
end

The variable moveDir stores the direction the player is moving and stepWidth and stepForward change the leg step positions, you can mess around with them and see what works best.

Finally, add the function to the RunService event and run the game, you should now see the character move much more realistically in all directions:

2025-10-19+17-45-53

Conclusion


And there you have it! with just over 100 lines of code we have completely procedurally generated walk animations! You can probably see how powerful this can be, and it’s not just for movement animations! You can use it in fps games for holding guns or in horror games for footplanting! In fact, while writing this topic, i made a simple gun holding animation:

2025-10-19+17-44-13

I hope you enjoyed this topic and learned something new!

16 Likes

The walking animation is a huge fail. But still that can be really useful and im happy somoene actually took time to write something about procedural animations looking forward to your next po
st. . .

1 Like

yeah i agree the walk animation could be a lot better, messing around with the values will make it a lot more realistic. I also added some foot lifting to make it more realistic and improved the foot animations. It’s more to just showcase what you can do with procedural animations but i agree with you.

1 Like

I understand after all procedurally animating anything is or a lot of math or trial and error and taking the time to do any of the two just for a showcase would have been a waste of time.

1 Like

Yeah thanks for understanding, i might make a follow-up post on how to actually make procedural animations look good or something like that

1 Like

I tried making something like this a while back for mechs walking over uneven terrain, in case you want to expand further:

  1. How to correctly setup constraints for the IK control intead of using R6 could be cool.
  2. Implementing something like a parabolic step with a “step height” as the turning point of the curve could also be cool.
  3. Also IK control can be unrealistic by themselves, I found blending them with stepping and running animations is the best approach.
    Otherwise pretty nice tutorial, well done!
1 Like

This is an extremely useful tutorial. Probably the hardest part of using IK for procedural animations is the initial setup and adjusting it so things visually look fine. Once everything is ready though, adding new weapons or tools are a breeze.

1 Like