Maintain Momentum on Boat When Player Jumps

The goal is to make it so that any player standing on a moving boat that jumps stays in the exact same spot they jumped on. Down bellow is the script I use for the boat (it isn’t a terrain boat)

I understand it is a physics related issue but here is a demonstration of what is happening now.

I have seen a post relating to what I am trying to achieve here: Player Momentum when jumping on moving boat

However, I cannot find a clear tutorial or method on how to use it so I am making this post to figure it out for all of us. The ‘solution’ post mentioned to use this: Releasing Character Physics Controllers

local boat = script.Parent
local settings = boat.Settings

-- Set max speed and initial movement
boat.MaxSpeed = settings.MaxSpeed.Value
local maxSpeed = boat.MaxSpeed
local acceleration = settings.Acceleration.Value
local turnSpeed = settings.TurnSpeed.Value

-- Initialize physics
boat.BodyPosition.Position = boat.Position
boat.BodyGyro.CFrame = boat.CFrame

local velocity = 0

-- Main loop
while true do
	wait()

	local throttle = boat.Throttle
	local steer = boat.Steer

	-- Handle throttle
	if throttle == 1 then
		if velocity < maxSpeed then
			velocity = velocity + acceleration
		end
		boat.Driving.Value = true

	elseif throttle == -1 then
		if velocity > -maxSpeed then
			velocity = velocity - acceleration
		end
		boat.Driving.Value = true

	elseif throttle == 0 then
		-- Gradually reduce velocity toward zero
		if velocity > 0 then
			velocity = velocity - acceleration
			if velocity < 0 then velocity = 0 end
		elseif velocity < 0 then
			velocity = velocity + acceleration
			if velocity > 0 then velocity = 0 end
		end
		boat.Driving.Value = velocity ~= 0
	end

	-- Apply movement force
	boat.BodyVelocity.Velocity = boat.CFrame.LookVector * velocity

	-- Reset steering flags
	boat.Left.Value = false
	boat.Right.Value = false

	-- Handle steering
	if steer == 1 then
		boat.BodyGyro.CFrame = boat.BodyGyro.CFrame * CFrame.fromEulerAnglesXYZ(0, -turnSpeed, 0)
		boat.Driving.Value = true
		boat.Right.Value = true

	elseif steer == -1 then
		boat.BodyGyro.CFrame = boat.BodyGyro.CFrame * CFrame.fromEulerAnglesXYZ(0, turnSpeed, 0)
		boat.Driving.Value = true
		boat.Left.Value = true
	end
end

I would really appreciate any help! God bless.

Here is some info that may help you. I remember a long time ago Badcc, jailbreak dev, was explaining how he did the train in jailbreak, which has the same physics. Its pretty simple, it has a collision box on the train to detect whether you are on the train or not, while a player is, every frame, it add apply the same change in position from the train to the player, so if in that frame the train moves 0.5 studs on the x scale, it adds that transform to the player’s position. if they jump off, that loop stops.

I was thinking something like that too but then I see the new character controller and this…

CharacterControllers do not magically do this. They use GroundSensors which you can set to Manual and use your own evaluation code, like standing on a moving platform moves you along with the platform if a Jump is registered.

For example, the GroundSensor in the ControllerManager senses a part under the supposed character, and you can use a script to determine if thats a part of a car or train, and then automatically retain velocity when the player jumps. The ground sensor also has custom height, unlike the humanoid, so it can continuously detect the part even if your feet have left the ground.

1 Like

You’ll need to delete the Humanoid and use a custom character controller. I made one in the past, but it’s really difficult.

This is how it is accomplished without deleting the Humanoid. Typically, they set the velocity of the character to a raycast that fires down at the ground.

Yes you’re correct, I was trying to express how it’d be done without the Humanoid as I believe it’d be similar in the specific example of jumping atop a car. The only other way I would imagine is the car is a part of your character and that sounds just more annoying than doing the velocity method.

Yes, but it might be more stable if you need to deal with network ownership to parent it to the character (the flinging effect is annoying though).

Very valid, I didn’t consider that.

How would you guys suggest I do it? @SubtotalAnt8185 @InfiniteYield

Actually, they don’t need to detect the ground or do some janky trick, AirControllers have a MaintainLinearMomentum property that does exactly what it says!

If you don’t need the behavior to be exactly the same with humanoids, you can use Character Controllers, there’s a setup and controller state machine script in the announcement topic, it will likely need some tweaks, but should achieve what you’re looking for.

I have looked through this a few times. Couldn’t find how…

Just download the lua source files and insert them where it says.
If you can’t directly insert the files into studio, create the necessary scripts, and copy-paste the source code in.

Tried. In the floor now :frowning:

I will try and debug these and see.


It works for me, did you set it up correctly?

I put InitializeCharacters in a server script in ServerScriptService. And I put the other in a local script in StarterCharacterScripts but I use R6 so I think that might be the issue.

That’s probably the issue, Humanoid.HipHeight seems to be always zero in R6, you’ll need to set the ground offset and sensor search distance manually.