Simulating smoother character movement?

I used one of the scripts and I keep getting this error on line 55
“moveVelocity = math.lerp( moveVelocity, targetMoveVelocity, math.clamp(dt * moveAcceleration, 0, 1) )”

 14:30:17.548  Players.Varsyte.PlayerScripts.MovementControl:55: attempt to call a nil value  -  Client - MovementControl:55

This is the code:

local RunS = game:GetService("RunService")
local InputS = game:GetService("UserInputService")

local player = game.Players.LocalPlayer
local camera = game.Workspace.CurrentCamera
local character = player.Character or player.CharacterAdded:Wait()

local targetMoveVelocity = Vector3.new()
local moveVelocity = Vector3.new()
local moveAcceleration = 8

player.CharacterAdded:Connect(function(_character)
	character = _character
end)

local walkKeyBinds = {
	Forward = { Key = Enum.KeyCode.W, Direction = Enum.NormalId.Front },
	Backward = { Key = Enum.KeyCode.S, Direction = Enum.NormalId.Back },
	Left = { Key = Enum.KeyCode.A, Direction = Enum.NormalId.Left },
	Right = { Key = Enum.KeyCode.D, Direction = Enum.NormalId.Right }
}

local function getWalkDirectionCameraSpace()
	local walkDir = Vector3.new()

	for keyBindName, keyBind in pairs(walkKeyBinds) do
		if InputS:IsKeyDown(keyBind.Key) then
			walkDir += Vector3.FromNormalId( keyBind.Direction )
		end
	end

	if walkDir.Magnitude > 0 then --(0, 0, 0).Unit = NaN, do not want
		walkDir = walkDir.Unit --Normalize, because we (probably) changed an Axis so it's no longer a unit vector
	end

	return walkDir
end

local function getWalkDirectionWorldSpace()
	local walkDir = camera.CFrame:VectorToWorldSpace( getWalkDirectionCameraSpace() )
	walkDir *= Vector3.new(1, 0, 1) --Set Y axis to 0

	if walkDir.Magnitude > 0 then --(0, 0, 0).Unit = NaN, do not want
		walkDir = walkDir.Unit --Normalize, because we (probably) changed an Axis so it's no longer a unit vector
	end

	return walkDir
end

local function updateMovement( dt )
	local humanoid = character:FindFirstChild("Humanoid")
	if humanoid then
		local moveDir = getWalkDirectionWorldSpace()
		targetMoveVelocity = moveDir
		moveVelocity = math.lerp( moveVelocity, targetMoveVelocity, math.clamp(dt * moveAcceleration, 0, 1) )
		humanoid:Move( moveVelocity )
	end
end	

RunS.RenderStepped:Connect(updateMovement)
2 Likes

Hi,
it looks like the culprit here is your attempt to call “math.lerp”. I was unable to find this function in the documentation: math | Documentation - Roblox Creator Hub

why dont works in mobile

because it only accepts keyboard input, theres nothing in there for mobile

Thank you so much for the script, because this post is just a mess.
But for some reason, my character isn’t able to jump anymore, once i use this script. Do you have any solutions? I couldn’t fix it myself.

okay, for everyones sanity, here’s a version that does not have the bug of slowing down when looking up/down and works on mobile:

local targetMoveVelocity = Vector3.new()
local moveVelocity = Vector3.new()
local Dir = CFrame.Angles(0,0,0)
local moveAcceleration = 5
local stopDecel = 10

local plr = game:GetService("Players").LocalPlayer
local RunS = game:GetService("RunService")
local InputS = game:GetService("UserInputService")
local CAS = game:GetService("ContextActionService")
local ctrlModule = require(plr:WaitForChild("PlayerScripts").PlayerModule:WaitForChild("ControlModule"))

local character = plr.Character or plr.CharacterAdded:Wait()
local camera = game.Workspace.CurrentCamera

local function lerp(a, b, t) return a + (b - a) * t end

local function getWalkDirectionCameraSpace()
	local walkDir = ctrlModule:GetMoveVector()

	if walkDir.Magnitude > 0 then
		walkDir = Vector3.new(walkDir.X, 0, walkDir.Z).Unit * walkDir.Magnitude
		if walkDir.Magnitude > 1 then
			walkDir = walkDir.Unit
		end
	end

	return walkDir
end

local function getWalkDirectionWorldSpace()
	local walkDir = camera.CFrame:VectorToWorldSpace(getWalkDirectionCameraSpace())

	if walkDir.Magnitude > 0 then
		walkDir = Vector3.new(walkDir.X, 0, walkDir.Z).Unit * walkDir.Magnitude
		if walkDir.Magnitude > 1 then
			walkDir = walkDir.Unit
		end
	end

	return walkDir
end

local function noY(vec:Vector3)
	return Vector3.new(vec.X,0,vec.Z)
end

local function updateMovement(dt)
	local humanoid = character:FindFirstChild("Humanoid")
	if humanoid then
		local moveDir = getWalkDirectionWorldSpace() 
		local deceleration = lerp(moveAcceleration, stopDecel, 1 - moveDir.Magnitude)
		targetMoveVelocity = moveDir
		moveVelocity = lerp(moveVelocity, targetMoveVelocity, math.clamp(dt * deceleration, 0, 1))
		humanoid:Move(moveVelocity)
	end
end

RunS.RenderStepped:Connect(updateMovement)
16 Likes

Absolutely Goated.

Thirty Minimum Characters :japanese_goblin:

1 Like

Hi,
the scripts you shared look very promising but I don’t know how to set them up. Can you show me where to store the scripts/modules and what’s inside them?
Thank you!

1 Like

the code fix returns a unit vector*

local runlean = root.CFrame:VectorToObjectSpace(root.AssemblyLinearVelocity - humanoid.MoveDirection)
runlean = Vector2.new(math.abs(runlean.X) >= .001 and math.floor(runlean.X * 1000 + 0.001) / 1000 or 0,runlean.Z <= math.huge and runlean.Z >= -math.huge and math.floor(runlean.Z * 1000 + 0.001) / 1000 or 0)

runlean should be a value you can tween the Torso’s Root Motor6D C1 with, simulating leaning the direction you run. Offsetting rotation on the HumanoidRootPart directly and using the new ControllerManager will cause a phenomenal momentum to happen just moving around, making movement REALLY SPICY

Try and use this but also at the start of the localscript put: local plr = game.Players.LocalPlayer

couldnt you just use a decaying lerp for the move vector in the playermodule where the humanoid:Move() function is?