Custom Water buoyancy not working properly

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
image

Actually, started trying a new approach to this and seems to be working better now.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.