Conserving Momentum in Air +Airstrafing, Surfing(bad) (Custom Character Controller)

For all my time on Roblox I was struggling with modifying the core character movement, but today I found out one of the best ways (that i know) and wanted to share it so people could find it easier.

Also made an uncopylocked place for it: untitled bhop game | Play on Roblox

I got the idea from this post. The basic idea is when the player is not touching the ground we set their Humanoid State to “Physics” which allows us to model how the player behaves in the air.

(you could also use Physics state on the ground but that would clutter my code even more and i think roblox’s ground controller is pretty good as is)


So if all you want is to conserve momentum in the air, all you would need is:

  • a Local Script inside StarterCharacterScripts
local RunService = game:GetService("RunService")

local char = script.Parent
local hum = char.Humanoid
local hrp = char:WaitForChild("HumanoidRootPart")

-- helper function to check for ground when humanoid is in Physics state
local function raycast()

	local params = RaycastParams.new()
	params.FilterType = Enum.RaycastFilterType.Exclude
	params.FilterDescendantsInstances = {char}

	local dir = Vector3.new(0, -1, 0)
	local origin = hrp.Position
	local result = workspace:Raycast(origin, dir * 5, params)

	return result
end

hum.StateChanged:Connect(function(old, new)
	if new ~= Enum.HumanoidStateType.Jumping and new ~= Enum.HumanoidStateType.Freefall then return end --when player jumps or falls
	
	hum:ChangeState(Enum.HumanoidStateType.Physics) --change state to Physics to customize the aerial movement
end)

RunService.Heartbeat:Connect(function(dt)
	if hum:GetState() ~= Enum.HumanoidStateType.Physics then return end --if player is not in the air / Physics state, skip this whole function
	
	--airAccelerate(dt) --optional: adding force on player input while airborne for air control by modifying hrp.AssemblyLinearVelocity
	

	if not raycast() then return end --check if player is touching ground
	
	hum:ChangeState(Enum.HumanoidStateType.Running) --transition back to grounded core state
end)

To see how Airstrafing and Surfing work you can check out the uncopylocked place.

[idk how to embed medal clips]

Note: the code is very messy and surfing doesn’t work as well as i’d like it to, maybe using a source-like approach to air_acceleration would fix that : p

I wasn’t able to make surfing much less buggy when using humanoid character.

However I fixed up an old project a bit and it’s basically a blank slate for a character controller.
It replaces the humanoid character controller with a ball, allowing for freeform scripting of movement without being ruined by buggy humanoid interaction.
[Medal Clip]