I created a script which allows for smooth walking acceleration and decelleration as I don’t really like the default movement behaviour that Roblox has. This is part of my game I am currently developing and just working out the mechanics and such.
Before
After
It is different from the other posts which accomplish the same task, some used the depreciated BodyGyro and some used Humanoid:MoveTo()
(which I ended up using).
The script works but I did notice some silly behaviour e.g. the character walking to 0,0,0 (which I found a fix for) and climbing on things can be very buggy.
Code
local Humanoid = script.Parent:FindFirstChild("Humanoid")
local brickRoot = Instance.new("Part",script.Parent)
brickRoot.Color = Color3.new(1,0,0)
brickRoot.Anchored = true
brickRoot.Transparency = 1
brickRoot.Size = Vector3.new(0.5,0.5,0.5)
brickRoot.CanCollide = false
local brickOffset = brickRoot:Clone()
brickOffset.Parent = script.Parent
brickOffset.Color = Color3.new(0,1,0)
brickOffset.Position = script.Parent.HumanoidRootPart.Position
local RunningSpeed = 0
local currentWalkSpeed = game.StarterPlayer.CharacterWalkSpeed
local DecellerationDistance = 2.2
local AccelerationTime = 0.25
local currentPosition = Vector3.zero
local currentAccelerationTime = 0
function smoothAcceleration(deltatime)
currentAccelerationTime += deltatime
Humanoid.WalkSpeed = currentWalkSpeed * math.clamp(currentAccelerationTime / AccelerationTime,0,1)
end
function SmoothWalking(deltatime)
local MoveDirection = Humanoid.MoveDirection
local HumanoidRootPart = script.Parent.HumanoidRootPart
local HumanoidPosition = HumanoidRootPart.Position
local RunningFloat = RunningSpeed / Humanoid.WalkSpeed
brickRoot.Position = HumanoidPosition
-- check if there is a drastic change in position e.g. a teleport
if (currentPosition - script.Parent.HumanoidRootPart.Position).Magnitude >= currentWalkSpeed then
warn("Magnitude too large for walk smoothing")
brickOffset.Position = brickRoot.Position
currentPosition = HumanoidRootPart.Position
return
end
local RootPosition = brickRoot.Position
local OffsetPosition = brickOffset.Position
local RootToOffsetMagnitudeFloat = math.clamp(((RootPosition - OffsetPosition).Magnitude) / DecellerationDistance,0,1) -- float decreases as root part is closer to offset
if MoveDirection ~= Vector3.zero then
brickOffset.Position = HumanoidPosition + (MoveDirection * DecellerationDistance * RunningFloat)
smoothAcceleration(deltatime)
else
currentAccelerationTime = 0
Humanoid:MoveTo(brickOffset.Position)
Humanoid.WalkSpeed = currentWalkSpeed * RootToOffsetMagnitudeFloat -- smooth decelleration
end
currentPosition = HumanoidRootPart.Position
end
Humanoid.Running:Connect(function(s)
RunningSpeed = s
end)
game:GetService("RunService").RenderStepped:Connect(SmoothWalking)
How it (basically) works
The script is located in StarterPlayerScripts
and creates a brick called “BrickOffset.”. BrickRoot may not be needed because HumanoidRootPart. It is always on front of the player’s walking direction and would remain offset from the HumanoidRootPart so that I can call Humanoid:MoveTo()
to the position of the brick offset when the player releases the key.
(The green brick is the Offset brick which helps determine where the player should decellerate to)
The speed of the player decellerates as it approaches much closer to the Offset brick to make it appear as if the player is decellerating from walking.
Acceleration is done by counting from 0 to 0.5 (seconds) in each render and turning that into a multiplier float for the walk speed.
So yeah, I didn’t spend that long on it, and I may probably not touch it again unless you have any improvements to the code and such. Suggestions welcome, thx for reading