How to make smooth character movement

Hello developers,

So i want to recreate smooth movement, but i have done over 2 hours of research, but nothing caught my eye, and most of them were outdated.

So i wanted to create a smooth movement, where instead of instantly stopping, you accelerate and deaccelerate. Does anyone has a script (doesn’t need a explanation, i think i would undertsand most of it). I am not familliar with coding playercharacters (its my first time).

Can someone help me?

3 Likes

I don’t know much about this, but a simple method is to slowly increase the speed when they start walking so it seems like they have momentum. I’ll give an example:

local char = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.Character:Wait()
local hum = char:WaitForChild("Humanoid")

local moving = false

local delayTime = 0.5
local speedIncrease = 1
local maxSpeed = 25
local startingSpeed = 10

function unMove()
	moving = false
	hum.WalkSpeed = startingSpeed
	--anything else you want after they stop walking
end

hum:GetPropertyChangedSignal("MoveDirection"):Connect(function()
	if hum.MoveDirection == Vector3.new(0,0,0) then
		if moving == true then
			unMove()
		end
		return
	elseif moving == false then
		moving = true
		while hum.MoveDirection ~= Vector3.new(0,0,0) and moving == true do
			if hum.WalkSpeed <= maxSpeed then
				hum.WalkSpeed+=speedIncrease
			end
			task.wait(delayTime)
		end
	end
end)
2 Likes

it gives a error at line 1

game.Players.LocalPlayer.Character:Wait()

:Wait()

maby you need to use getservice (i am trying to fix it rn), i think you need CharacterAdded:Wait() instead of Character:Wait()

1 Like

I tried this out, and this is good, but i needed acceleration, what you done here is smart, but if you just keep moving, the player will still build up speed, and can still instantly turn back.

that’s why i made a note in the unMove() function saying that you can change it however you want. Instead of setting the walkspeed to a number, just decrease by 1 until they start moving or it gets to that number

so you want players can’t turn back instantly?
you want them spin like the mid point is in the back?

thats not the problem, they keep moving but in different directions without deaccelerating, so the function unmove will not even start.

What he means is that turning around would take a little more sensitivity , turning around would be slower and smoother

I don’t fully understand what you mean, but basicly i want instead of letting a player instantly walk somewhere, they need to accelerate, and make it so that they cannot turn too much, because they need to change dirictions, and how faster you are, how longer it takes to turn

yes, also starting to walk will also accelerate, instead if instantly walking, so that its smooth andmore realistic

well i guess every time thier move direction changes you could lower the walkspeed so it can build back up, although it won’t work if they change their direction by turning their camera.

Edit: I made a super janky system but I think it works, feel free to tweak it

local char = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.Character:Wait()
local hum = char:WaitForChild("Humanoid")

local moving = false

local movingLV = char.HumanoidRootPart.CFrame.LookVector

local delayTime = 0.5
local speedIncrease = 1
local maxSpeed = 25
local startingSpeed = 10

function unMove()
	moving = false
	hum.WalkSpeed = startingSpeed
	--anything else you want after they stop walking
end

hum:GetPropertyChangedSignal("MoveDirection"):Connect(function()
	if hum.MoveDirection == Vector3.new(0,0,0) then
		if moving == true then
			unMove()
		end
		return
	elseif moving == false then
		moving = true
		while hum.MoveDirection ~= Vector3.new(0,0,0) and moving == true do
			if hum.WalkSpeed <= maxSpeed then
				hum.WalkSpeed+=speedIncrease
			end
			task.wait(delayTime)
		end
	end
end)

while task.wait() do
	if moving == true then
		if movingLV ~= char.HumanoidRootPart.CFrame.LookVector then
			 e = movingLV - char.HumanoidRootPart.CFrame.LookVector
		
		local a = e.X if a<0 then a=0-a end
		local b = e.Z if b<0 then b=0-b end
			if a+b >= 0.5 then
				print("A")
				local o = hum.WalkSpeed
				local w = math.ceil(((a+b)/hum.WalkSpeed)*10)
				if hum.WalkSpeed - w >= startingSpeed then
					--print(o, hum.WalkSpeed - w, a+b,(a+b)/hum.WalkSpeed,((a+b)/hum.WalkSpeed)*10)
					hum.WalkSpeed -= w
				end
				
			end
			movingLV = char.HumanoidRootPart.CFrame.LookVector
		end
	end
end

the code is pretty ugly and I had to use a while loop but it still kinda works

2 Likes

sorry for the wait, thats a good script you made, but it still isn’t smooth. When you stop walking you also instantly stop walking, thats also a problem we need to fix.

1 Like

well i think I’ve provided enough code for you to do the rest. The devforum really isn’t for asking for people to write your code for you, but instead for getting suggestions on how to fix or make your own code.

I do have a suggestion though. When they stop walking or turn directions you could give them a brief decreasing vector force in the direction the they were last facing.

1 Like

in your 2 hours of research i found it in 5 seconds of typing Simulating smoother character movement? - #3 by ThanksRoBama

1 Like

i already found that, it was outdated ):

but its literally not? you can easily use it

I replaced ControlScript, and i just couldend walk after i did the tutorial

well then you did it wrong. i used it and did it and it works perfectly fine

just read through the posts in the topic

1 Like

I did the tutorial again, but there’s an error:


Here’s the code i made

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 = lerp( moveVelocity, targetMoveVelocity, math.clamp(dt * moveAcceleration, 0, 1) )
		humanoid:Move( moveVelocity )
	end
end	

RunS.RenderStepped:Connect(updateMovement)

Do you know how to fix this?

1 Like

I Fixed the error but now i see a warn:
image
I think the controlscript is updated