Hello! I’m working on a game similar to “Build a boat for treasure”..
I have a custom ship/boat system in my game.
I’m using AngularVelocity for left/right steering. It technically works however the boat kinda “drifts” on water when turning. I’m aiming for sharper turns.
below is a snippet of my code that handles movement
local root = boat:FindFirstChild("PhysicsRoot")
if not root then
boat.SFX.SplashWater:Play()
root = Instance.new("Part")
root.Size = Vector3.new(4,1,4)
root.Position = primary.Position
root.Anchored = false
root.CanCollide = true
root.Transparency = 1
root.Name = "PhysicsRoot"
root.Parent = boat
root.CFrame = primary.CFrame + Vector3.new(0,0,-5)
local bv = Instance.new("BodyVelocity")
bv.MaxForce = Vector3.new(1e5,0,1e5)
bv.Velocity = Vector3.new(0,0,0)
bv.Name = "BoatVelocity"
bv.Parent = root
local bg = Instance.new("BodyGyro")
bg.MaxTorque = Vector3.new(1e5,0,1e5)
bg.P = 5000
bg.D = 500
bg.Parent = root
local angular = Instance.new("BodyAngularVelocity")
angular.MaxTorque = Vector3.new(0,1e9,0)
angular.Name = "BoatAngular"
angular.AngularVelocity = Vector3.new(0,0,0)
angular.Parent = root
local weld = Instance.new("WeldConstraint")
weld.Name = "RootWeld"
weld.Part0 = root
weld.Part1 = primary
weld.Parent = root
end
for _, part in ipairs(boat:GetDescendants()) do
if part:IsA("BasePart") and part ~= root then
part.CanCollide = false
PhysicsService:SetPartCollisionGroup(part, "BoatParts")
end
end
local maxSpeed = boat:GetAttribute("MaxSpeed") or 50
local baseSpeed = maxSpeed * 0.2
local targetSpeed = baseSpeed
if throttle > 0 then
targetSpeed = maxSpeed
end
if fuel <= 0 then
targetSpeed = 0
end
local bv = root:FindFirstChild("BoatVelocity")
if bv then
local tween = TweenService:Create(bv, TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), {Velocity = root.CFrame.LookVector * targetSpeed})
tween:Play()
end
local angular = root:FindFirstChild("BoatAngular")
if angular then
local fixedTurnRate = math.rad(25)
local steerClamped = math.clamp(steer, -1, 1)
local targetAngular = Vector3.new(0, -(steerClamped * fixedTurnRate), 0)
if fuel <= 0 then targetAngular = Vector3.new(0,0,0) end
angular.AngularVelocity = targetAngular
end
local gyro = root:FindFirstChildOfClass("BodyGyro")
gyro.MaxTorque = Vector3.new(1e5,0,1e5)
gyro.P = 5000
gyro.D = 500
local tiltForward = math.clamp((targetSpeed / maxSpeed) * 10, 5, 10) * .5
local tiltSide = math.clamp(steer, -1, 1) * 1.5
local goalCFrame = CFrame.new(root.Position, root.Position + Vector3.new(root.CFrame.LookVector.X, 0, root.CFrame.LookVector.Z))
* CFrame.Angles(math.rad(tiltForward), 0, math.rad(-tiltSide))
local tiltTween = TweenService:Create(gyro, TweenInfo.new(0.3, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), {CFrame = goalCFrame})
tiltTween:Play()
I use BodyVelocity for forward movement, AngularVelocity for steering and a BodyGyro for tilting effect.
this is what I’m trying to achieve
all help is appreciated! thanks for your time.