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:

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:

I hope you enjoyed this topic and learned something new!
