Hello there!
I’m currently working on a sea game and am trying to make a boat with buoyancy. I thought of getting something very simple working first, so I’m attempting to make a boat bob up and down a bit in the water and respond to waves by only comparing a single point (the closest vertex of the water mesh to the center of the boat) to get how much the boat is submerged, however with my current solution, the bobbing is very exaggerated and aggressive or too fast.
A quick clip of what I mean:
Although it does eventually even out more, it just stays pretty much constantly evenly submerged under the water and doesn’t really bob at all at that point. Probably because of drag.
I’m trying to make the buoyancy somewhat like in this video at 8:30 right now https://www.youtube.com/watch?v=ja8yCvXzw2c&t=485s.
The part that controls the buoyancy (buoyancyPart in code) looks like this:
And of course, the code:
local y_velocity = 0
local function Update(deltaTime: number)
UpdateVariables()
local boatPos = boat:GetPivot().Position
local boatHeight = boatPos.Y - buoyancyPart.Size.Y/2
local heightAtCenter = GetWaterHeightAtPos(boat:GetPivot().Position)
local underWaterY = math.clamp(heightAtCenter - boatHeight, 0, buoyancyPart.Size.Y)
local underWaterPercent = underWaterY / buoyancyPart.Size.Y
local displacedVolume = GetBoatVolume() * underWaterPercent
local force = waterDensity * displacedVolume * gravity
y_velocity += force * deltaTime / buoyancyPart.Mass
y_velocity -= gravity * deltaTime
if y_velocity > 0 then
y_velocity = math.max(y_velocity - airDrag * deltaTime * (1 - underWaterPercent) - waterDrag * deltaTime * underWaterPercent, 0)
else
y_velocity = math.min(y_velocity + airDrag * deltaTime * (1 - underWaterPercent) + waterDrag * deltaTime * underWaterPercent, 0)
end
local pos = Vector3.new(boatPos.X, boatPos.Y + y_velocity * deltaTime, boatPos.Z)
boat:PivotTo(CFrame.new(pos) * boat:GetPivot().Rotation)
end
RunService.Heartbeat:Connect(Update)
I’ve tried to implement air and water drag / resistance, but they haven’t helped much.
For the unknowns in the code, UpdateVariables
just updates the drag and water density according to the set attributes, GetBoatVolume
returns the volume of the buoyancy part and GetWaterHeightAtPos
returns the world Y position of the closest vertex of the water mesh to the boat’s position.
Now, since in the goal (aka the youtube video), the part that has buoyancy applied to it is a cube and far taller than the boat’s one, so that would probably cause part of the exaggeration since the entire boat gets submerged much quicker. I’m just not sure what is wrong in the code. I’ve been tweaking the variables for the drag and water density, but I’ve always ended up with the boat either not bobbing, bobbing far to much / too fast or getting bounced into the air.
Oh right, and the current settings