EDIT EDIT EDIT EDIT
There’s a bug in the code I posted. It’s quite easy to fix, see what it is and how to fix it here:
Thanks to @dthecoolest for catching it Now here’s the rest of the comment:
Can’t tell if you want character to accelerate slower without changing physical properties, or if you want to normally with changed physical properties.
EDIT: nvm, figured it out Making proper reply
I would make a custom movement script from scratch that uses the built-in humanoid movement system, but manually managing the exact movement velocity so instead of each direction being only on/off, it gradually reaches a target velocity.
Basic movement script that has the old beahvior (put in a LocalScript called ControlScript in game.StarterPlayer.StarterPlayerScripts)
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()
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
humanoid:Move( getWalkDirectionWorldSpace() )
end
end
RunS.RenderStepped:Connect(updateMovement)
The thing that we’ll change to make the character slowly get up to speed is the updateMovement
function. I’ll add this to the top of the script:
local targetMoveVelocity = Vector3.new()
local moveVelocity = Vector3.new()
local moveAcceleration = 8
and this is the new updateMovement
function:
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
Every frame it makes the actual velocity a little closer to the target velocity. It changes by a small fraction every update. This fraction is determined by the frame-frate and the moveAcceleration
, which represents the acceleration from a complete stand-still. All of this causes it to asymptotically go towards the target velocity, which means as it gets closer to the target speed, it accelerates slower and slower, so we get a very smoothed-out speed change as it gets up to speed or slows down, but it still accelerates pretty fast and feels pretty responsive when the player suddenly changes direction.
It could definitely be improved to feel a lot more responsive, but this is a super simple example you can build off of.
Does this help? Let me know if you need help getting the scripts to work or have questions