Character controller movement help

I got a custom character controller but ive been having diffuculties actually getting movement in. I have the inputs and physics all working but cant figure out how to actually get the character to move the way i want to:

-- Main movement (MovementVector --> input direction relative to the camera)
function MovementController.Move(MovementVector: Vector3, DeltaTime: number): ()
	
    -- All client vars
	local currentVelocity: Vector3 = Client.Velocity --> the velocity of the character
	local groundNormal: Vector3 = Client.GroundNormal --> the normal of the surface or vector.zero if not grounded
	local grounded: boolean = Client.Grounded --> is on a surface
	local onSlope: boolean = Client.OnSlope --> is on a slope above the max slope angle
	
    -- All player movement settings
	local gravity: Vector3 = MovementSettings.Gravity
	local maxSlope: number = MovementSettings.MaxSlope
	local friction: number = MovementSettings.BaseFriction
	
    -- Getting the correct speed
	local moveSpeed = MovementSettings.WalkSpeed
	moveSpeed += Client.Sprinting and 12 or 0
	moveSpeed += Client.Crouching and -6 or 0
	
    -- Extremely basic and non reliable movement (just an example)
	currentVelocity += MovementVector * moveSpeed
	Client.Velocity += currentVelocity * DeltaTime
end

-- Apply gravity
function MovementController.Gravity(DeltaTime: number): ()
	if Client.Grounded then return end
	Client.Velocity += MovementSettings.Gravity * DeltaTime
end

-- Make the character jump
function MovementController.Jump(MovementVector: Vector3): ()
	if not Client.Grounded then return end
	Client.Velocity += Vector3.yAxis * MovementSettings.JumpForce
end

what ive been trying to do is add acceleration, friction and make it so you slide down slopes that are above the max slope angle. I have tried so many different combos of different things and im kinda just out of brain power now

1 Like

I’m a little confused as the code doesn’t really do any of those, but alright.

Acceleration should be rather simple. Just add MoveDirection * accelerationSpeed * deltaTime to the player’s velocity every frame and optionally clip it to a maximum velocity with

if velocity.Magnitude > 0 then
    velocity = velocity.Unit * math.min(velocity.Magnitude, maxVelocity)
end

(Depending on the movement system, you may actually want to clip the x and z velocity separately so that jumping/falling wouldn’t affect it)

For friction, there’s this nice formula

velocity *= math.exp(-k * deltaTime)

Where k is the strength of the friction

Again, you might want to apply it separately to the X and Z axis when the player is grounded and add some air friction to the Y axis or to all axes when the player is mid-air.

As for sliding down a slope, you’ll probably need to use a raycast from the player down to the ground to get the normal vector of the ground (essentially which way the ground is)
Now with the normal vector you can calculate which way is downhill like so

local downDirection = g - n * g:Dot(n)
local downMagnitude = downDirection.Magnitude
downDirection = downDirection.Unit

Where g is the gravity direction ( usually (0, -1, 0) ) and n is the normal direction you got from the raycast
And then you can apply an acceleration toward that direction depending on the steepness (downMagnitude)

velocity += downDirection * downMagnitude * gravity_or_sliding_mult * deltaTime

I extracted the magnitude and direction separately in case you need to do something more custom, but you don’t need to do so per say as the code above just multiplies the direction and magnitude back together.

Hope this helps!
Lmk if I explained something too broadly.