Calculating / Retaining Player Momentum

Hey all, I’m trying to add player momentum to my game so that when you run over the edge of a ramp / jump off of an edge / bounce off of rebound surfaces etc. you retain the velocity you were moving at before. I’ve tried many times to write a script similar to the one below, which sort of works, but not in the way I want it to.

I calculate the player’s direction from their current position and the position they were in the previous frame, add on the velocity they last had but slightly diminished so that you gradually lose momentum as you move, and then slowly lerp the velocity to 0, 0, 0 so that you eventually lose all velocity. However, the player gains momentum in weird ways, such as flinging sideways or losing all forward velocity when jumping off of an edge.

I think I’m going about this the wrong way and also I don’t know exactly how to calculate proper momentum. I’ve looked at many different topics about momentum on the devforum but they only say to use bodymovers, which I am using, instead of giving a method of properly calculating momentum.
If anyone can assist me in properly calculating momentum, please help me!

local Humanoid		= Character:WaitForChild("Humanoid")
local Root			= Humanoid.RootPart

local BM 		= Instance.new("BodyVelocity")
BM.MaxForce		= Vector3.new(4000, 1000, 4000)
 -- Vertical velocity is less important and also causes the player to stutter in the air
BM.P			= 5000
BM.Parent 		= Root

local LastVelocity	= Root.Velocity -- Should be 0,0,0 but just in case
local LastPoint = Root.Position

RunService.Stepped:Connect(function()
	local Hit, Pos, Norm = Raycast(Root.Position, Root.Position - Vector3.new(0, 3, 0), {Character})
	-- Generic raycast function: Simply fires a ray downward, ignoring the character's parts.
	

	if not Hit then
		-- Momentum will only be kept in the air!
		local Direction = (Root.Position - LastPoint).Unit * math.clamp((LastVelocity.Magnitude * 0.99), 1, 100)
		LastVelocity	= Direction:Lerp(Vector3.new(), 0.001)
		BM.Velocity		= LastVelocity
	else
		BM.Velocity = BM.Velocity:Lerp(Vector3.new(), 0.1)
		-- Set velocity back to 0,0,0 faster as we are now on a surface (emulate friction)
	end
	LastPoint	=	 Root.Position
	-- Set the current position as the last position so we can calculate the direction of movement
end)

I use raycasts to check when the player is standing on the floor, in which case I then remove the velocity faster so that they can walk normally again with a small amount of sliding when they first land.

My question is this: How can I properly calculate the momentum of a player and then implement it in a realistic way?

2 Likes