As seen in this video, when I walk into a wall on my boat, it pushes the boat in whichever direction the player is walking.
I’ve tried:
Increasing the density of the boat, but that causes it to sink.
Using BodyPosition, but this has tons of side effects that aren’t worth it. This includes flinging and unrealistic collisions.
Moving the mass of the boat underneath the boat – as I’ve seen in other suggestions. This yielded no results.
Any suggestions on how I can prevent this? I’m hoping to make it so the boat can still be pushed by other boats or even if there’s enough players pushing the boat at once.
Honestly I’m pretty stumped on how you would fix that without side effects.
One potential fix I can think of is writing code to set the walkspeed to a low value when the character is standing on the boat and not moving relative to the boat while having a non-zero move direction.
The other would be to increase the density of the boat a lot then add a VectorForce to counter act the extra weight. The buoyancy force is proportional to the amount of water displaced, so if you increase the density then counter the extra gravitational force it would be the same as before (but your boat would have more inertia and be harder to get moving).
I might give that second one a try, as it seems promising. My only concern is that with more inertia, there’s more chance of flinging.
One other thing I might try is doing all my boat movement and physics simulation in one collision group, and all my character collisions in another collision group. That way, I can just have a mesh that acts as the collisions for the boat and set the CFrame of that to be in the right location. Then to keep the player synced with the momentum of the boat, just use a similar system to jailbreak’s train system.
I’ll let you know what I find. Thanks for the help and brainstorming this.
You could have the mesh be created+updated on each client for it to be very accurate. If you use a AlignPosition + AlignOrientation you could also have the character still “stick” to the boat (if you only use CFrame the character won’t move with the boat when the boat moves).
I tried CFrame and got momentum working on it. However, it was jittery. So I moved to your suggestion of the AlignOrientation and AlignPosition. This works, but seems to be miscalculating the forces applied to the character as seen in the video.
Any suggestions? If not, I’ll just settle for the jittering of CFrame. Thanks!
I ended up going back to CFrame but using your suggestion of rendering the collisions only on the client. Then I used this code to sync momentum:
--BrahGames 07-27-2021 rewritten https://devforum.roblox.com/t/jailbreak-train-platform-system/236339
--slightly edited to work with bodymovers and such /maxx
local Players = game:GetService("Players")
local player = game.Players.LocalPlayer
local RunService = game:GetService('RunService')
local CheckStates = true
local LastPartCFrame
local LastPart
local Function
local Function2
function CFrameLogic(Raycast, CFramePart)
--------------------------------------------------------------- MOVE PLAYER TO NEW POSITON FROM OLD POSITION
if Raycast.Instance ~= LastPart then
LastPart = Raycast.Instance
LastPartCFrame = nil
end
local Train = Raycast.Instance
if LastPartCFrame == nil then -- If no LastTrainCFrame exists, make one!
LastPartCFrame = Train.CFrame -- This is updated later.
end
local TrainCF = Train.CFrame
local Rel = TrainCF * LastPartCFrame:inverse()
LastPartCFrame = Train.CFrame -- Updated here.
CFramePart.CFrame = Rel * CFramePart.CFrame -- Set the player's CFrame
--print("set")
end
Function = RunService.Heartbeat:Connect(function()
--------------------------------------------------------------- CHECK PLATFORM BELOW
-- Build a "RaycastParams" object
local HumanoidRootPart = player.Character.HumanoidRootPart
local humanoid = player.Character.Humanoid
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Include
raycastParams.FilterDescendantsInstances = {game:GetService("CollectionService"):GetTagged("BoatCollisions")}
raycastParams.IgnoreWater = true
raycastParams.CollisionGroup = "Default"
-- Cast the ray
local Hit = workspace:Raycast(HumanoidRootPart.CFrame.p, Vector3.new(0,-15,0), raycastParams) --Casts a ray facing down
--------------------------------------------------------------------------------------------
if Hit then -- Check if the ray hits and if it hits an object inside of MovingObjects
if CheckStates then -- check if the character is jumping
local currentState = humanoid:GetState()
--if currentState == Enum.HumanoidStateType.Freefall or currentState == Enum.HumanoidStateType.Jumping or currentState == Enum.HumanoidStateType.FallingDown then
CFrameLogic(Hit, HumanoidRootPart)
--else
--LastPartCFrame = nil -- Clear the value when the player gets off.
--end
else
CFrameLogic(Hit, HumanoidRootPart)
end
else
LastPartCFrame = nil -- Clear the value when the player gets off.
end
end)
Function2 = player.Character.Humanoid.Died:Connect(function()
Function:Disconnect() -- Stop memory leaks
Function2:Disconnect() -- Stop memory leaks
end)
It’s a slightly modified version of the code from this post.