The orientation is calculated with the following code:
local b = Instance.new("BodyPosition", chassis)
local chassis = workspace.Boat.Chassis
local joints = workspace.Boat.Joints
game:GetService("RunService").Heartbeat:Connect(function()
local frontLeft = joints.FL.Position
local backLeft = joints.BL.Position
local backRight = joints.BR.Position
local backLeft = joints.BL.Position
local front = (frontLeft - backLeft).unit
local right = (backRight - backLeft).unit
local up = right:Cross(front)
local x = (joints.FR.Position.X + joints.BL.Position.X)/2
local y = (joints.FR.Position.Y + joints.BL.Position.Y)/2
local mass = chassis.Mass.WorldPosition
local result = CFrame.new(x, y, 82, right.x, up.x, -front.x, right.y, up.y, -front.y, right.z, up.z, -front.z )
local pitch, yaw, roll = result:toEulerAnglesXYZ()
b.position = Vector3.new(x, y, 82)
b.maxForce = Vector3.new(500000000, 500000000, 500000000)
chassis.Mass.BodyGyro.CFrame = result
end)
As you can see though, it acts weird when a human sits/touches it.
This is how it acts when no one is sitting/touching it (and this is how it should be when someone is touching/sitting on it).
I’m not sure of the exact physical model of your boat (as you seem to have multiple forces, not sure if the “Joints” have force in them?), but it seems like your BodyGyro force in the main chassis is attempting to correct for the tilt due to you standing on it. However, it over corrects and start oscillating. Try to tune the P and D values of the BodyGyro as well as limit MaxTorque to something reasonable.
For some reason when I hit run, it just decides to go underwater. I have tried lifting it up above water using the move tool, but then it flies back down underwater.
Inside if OrientationCalculator it sets the position of the BodyPosition force: b.position = Vector3.new(x, 2.5, 82)
I had it like that to test the “wave handling” mechanics