Boat buoyancy not properly working

I have a skinned-mesh ocean and I want to make things float. I attached a video and as you can see it kind of works but not entirely. I was wondering why this is and if anyone has any idea on how to fix / improve this. Thanks!

Ocean Script:

local RunService = game:GetService("RunService")
local waveModel = workspace:WaitForChild("Wave")
local plane = waveModel:WaitForChild("Plane")
local bones = {}
for _, v in ipairs(plane:GetDescendants()) do if v:IsA("Bone") then table.insert(bones, v) end end

local amplitude, wavelength, speed = 2, 32, 2

local function waveOffset(basePos, t)
	local height = amplitude * math.sin((basePos.X + basePos.Z) / wavelength - speed * t)
	return Vector3.new(0, height, 0)
end

local boneData = {}
for _, bone in ipairs(bones) do
	local pos = bone.CFrame.Position
	boneData[#boneData+1] = {bone = bone, originCFrame = bone.CFrame, originPos = pos}
end

RunService.Heartbeat:Connect(function()
	local t = tick()
	for _, d in ipairs(boneData) do
		local offset = waveOffset(d.originPos, t)
		d.bone.CFrame = d.originCFrame * CFrame.new(offset)
	end
end)

_G.GetWaveHeightAt = function(position)
	return amplitude * math.sin((position.X + position.Z) / wavelength - speed * tick())
end

Buoyancy Script:

local RunService = game:GetService("RunService")
while not _G.GetWaveHeightAt do wait() end
local folder = workspace:WaitForChild("BuoyantParts")
for _, m in ipairs(folder:GetChildren()) do
	if m:IsA("Model") and m.PrimaryPart then
		local p = m.PrimaryPart
		p:SetNetworkOwner(nil)
		p.BodyPosition.MaxForce = Vector3.new(1e5,1e5,1e5)
		p.BodyGyro.MaxTorque  = Vector3.new(1e5,1e5,1e5)
	end
end

RunService.Heartbeat:Connect(function()
	for _, m in ipairs(folder:GetChildren()) do
		if m:IsA("Model") and m.PrimaryPart then
			local p, cf = m.PrimaryPart, m.PrimaryPart.CFrame
			local fY = _G.GetWaveHeightAt((cf*CFrame.new(0,0,-40)).Position)
			local bY = _G.GetWaveHeightAt((cf*CFrame.new(0,0,50)).Position)
			local rY = _G.GetWaveHeightAt((cf*CFrame.new(10,0,0)).Position)
			local lY = _G.GetWaveHeightAt((cf*CFrame.new(-10,0,0)).Position)
			local hover = _G.GetWaveHeightAt(cf.Position) + p.Size.Y/2
			local _, yaw, _ = cf:ToOrientation()
			local angX = math.atan2(fY - bY, 90)
			local angZ = math.atan2(rY - lY, 20)
			p.BodyPosition.Position = Vector3.new(cf.Position.X, hover, cf.Position.Z)
			p.BodyGyro.CFrame        = CFrame.Angles(0, yaw, 0)*CFrame.Angles(angX,0,angZ)
		end
	end
end)

Video:

Again, any ideas would be amazing. Thanks!

Maybe its like a delay on the server ping?

It’s almost like your hover position is going too far in either direction. What if you multiply it by a percentage like 70%.
You know your basic wave height baseline already (the position of your Mesh water surface when there are no waves).
Your sine wave is the baseline + or - the WaveHeight.
Multiply that difference by .7 (or whatever works) to get your Hover value.

1 Like

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