# Making a Boat Tilt

I’m working on a boat script, and I want the boat to tilt with BodyGyro, the problem is if I do it like that then turning the boat left and right to steer will effect the way the boat turns differently.

``````seat = script.Parent
gyro = seat.BodyGyro
pos = seat.BodyPosition
vel = seat.BodyVelocity

pos.position = seat.Position
gyro.cframe = seat.CFrame
speed = 0
wait()
seat.Anchored = false

local movingRight = false
local movingLeft = false

function move(property)
if property == "Steer" then
return
end
local steer = seat.Steer
while steer ~= 0 do
steer = seat.Steer
if steer == 1 then
movingRight = true
movingLeft = false
gyro.cframe = gyro.cframe * CFrame.fromEulerAnglesXYZ(0,-.1,0)
elseif steer == -1 then
movingLeft = true
movingRight = false
gyro.cframe = gyro.cframe * CFrame.fromEulerAnglesXYZ(0,.1,0)
end
wait()
vel.velocity = seat.CFrame.lookVector * speed
end
elseif property == "Throttle" then
while property == "Throttle" do
local throttle = seat.Throttle
if throttle == 1 and speed < seat.MaxSpeed then
speed = speed + 1
elseif throttle == -1 and speed > 0 then
speed = speed - 1
end
wait(.1)
vel.velocity = seat.CFrame.lookVector * speed
end

end
end

seat.Changed:connect(move)
``````
10 Likes

I’ve learned that the best way to control a boat in Roblox. Is to not control a boat in Roblox. Now this is gonna sound crazy but.

I make my boat get represented by a single part. Then I manipulate that part. The only thing the boat needs to do is match its orientation with that part. You get pretty natural behavior like this.

That’s exactly what this script does, however it still doesn’t solve the issue in the matter. When you rotate the boat, it’s on the X coordinate, but tilting it would mess up the coordinate making the boat float in the air sorta.

You can tell I’m only manipulating 1 part because the first variable is Seat = script.Parent

EDIT: Also when I say making the boat tilt I mean the bodygyro manipulating the seat

1 Like

Yeah I don’t use any “real” bodymovers in the boat. The ones I use are these.

I actually can’t see what the problem would be with your code. It’s not like you’re rotating it on two axis at the same time… Have you tried dropping the force values on axis you aren’t manipulating?

The script I showed you has 0 problems at all. The problem is when I try to add to the Z axis for the gyro. It’s supposed to tilt the way you turn, that’s the way I’m trying to make it. Here’s an example of what worked, but not the way I planned it to;

``````gyro.cframe = gyro.cframe * CFrame.fromEulerAnglesXYZ(0,-.1,.3) -- added to the Z Axis
``````

After doing this in the script, it forces the boat to spin in circles rather than tilting. I just want it to tilt the boat which way youre steering

The Y axis will rotate the ship in a circle. In this case though you’re manipulating both axis at once. You should modify the Z axis on another line to rotate on the Y first then Z. In this case you’re rotating on the Y and Z at the same time so you’re ending up with entirely different behavior.

I’ll give that a try real quick.

same problem;
https://gyazo.com/f8bb04d956dd6b4c7434871069be03f7

I did as said this way;

``````	gyro.cframe = gyro.cframe * CFrame.fromEulerAnglesXYZ(0,0,0)
gyro.cframe = gyro.cframe * CFrame.fromEulerAnglesXYZ(0,0,.1)
``````
2 Likes

Hmm that’s all I know

Instead of doing `gyro.CFrame = gyro.CFrame * ...`, which is additive, I think you should include it in a fresh construction of the CFrame.

This is usually done by checking each frame or so if a WASD key is held down, and if it is, add it to a variable that creates the CFrame. It won’t be needed here though since you check using `Steer`.

It looks like we can do this all in your `steer` block, and you have your logic built for it already.

So what I would do is have a `steerY` variable outside of `move` that adds/subtracts 0.1 when steering in a direction, and assign Z to a specific number based on which direction it’s steering in as well. Then I would construct a brand new CFrame, independent from the last, with Z in mind already:

``````local steerY = 0

if not ready then return end
local steer = seat.Steer
while steer ~= 0 do
steer = seat.Steer
local steerZ = 0
if steer == 1 then
movingRight = true
movingLeft = false
steerY = steerY - 0.1
steerZ = 0.3
elseif steer == -1 then
movingRight = false
movingLeft = true
steerY = steerY + 0.1
steerZ = -0.3
end
gyro.CFrame = CFrame.Angles(0, steerY, 0) * CFrame.Angles(0, 0, steerZ)
end
-- end steer block
``````

This new `steer` should do what you want. You might want to change the signs on `steerY` and `steerZ` operations, though they should be opposite from each other when steering in the other direction.

7 Likes

OK, here is my crazy idea.

What if you created an alternating loop.
The loop applies the one axis of force on evens. Wait .2 second, then applies the other axis of force on odd runs.

This reduces the stress on the physics engine but could get the same desired result. I find what is right and what works are often two different things.

2 Likes

Make the velocity not act out in the Y axis by making the MaxForce in the Y axis 0, then it shouldn’t fly upwards or downwards at all.

Also for the tilting, remeber that you’re making the gyro tilt continously on it’s same position constantly, you should probably only want to turn based on the seating. Maybe add some variables if you don’t want it to tilt too far.

I did this exact thing a while back, what i did was create a motor that had two parts: a handle and a controller. The handle was the part1, and all of the other ship parts were welded to it. The controller was the part0, and it had a gyro force along with a velocity force. To turn the ship or move it, I would modify the forces on the controller. To tilt it I would just set the desired angle of the motor. The controller was the master object; it was in charge of all of the ship’s movement and I could easily do all sorts of things with it. Meanwhile, having that motor that indirectly connected it to the rest of the parts on the ship allowed for a nice swaying mechanic to have on the side.

(Edit; this wasn’t intentionally replying to goldenstein)

Don’t use a gyro, just use a RootPart and CFrame it. No reason to use a gyro, you end up with weird behaviour like this.

To get the same nice rocking motions (i.e accelerating through the middle, decelerating towards the end of the title) you can use a mathematical function. Your code will look a little like this

``````local rad = 180/math.pi --convert degrees to radians
local maxSway = 20 * rad
local swayTime = 5 -- the time for it to go from 20 degrees one way, to the other

local boat = workspace.Boat

local startTime = tick()

function easingStyle(i)
--this function basically has to take a number 0-1 and return a number from -1 to 1 with some easing effect added.
i = (i-.5) * 2
return -1 + 2 * i ^ 2
end

game:GetService("RunService").HeartBeat:Connect(function()
local runTime = tick() - startTime
local animationProgress = (runTime % swayTime)/swayTime -- return a scalar 0-1

local swayRadians = (maxSway * animationProgress)
end)
``````

some of the logic there is probably wrong, but its a pretty simple calculation to set up

3 Likes

Blockquote
local seat = script.Parent
local speed = 0
local bv = script.Parent.BodyVelocity
local bg = script.Parent.BodyGyro

seat.Changed:Connect(function(Direction)
if Direction == “Thtottle” then
wait()
if seat.Throttle == 1 then
if speed < seat.MaxSpeed then
speed = speed + 0.5
end

``````		bv.Velocity = script.Parent.CFrame.LookVector * speed
elseif seat.Throttle == 0 then
if speed > 0 then
speed = speed
elseif speed < 0 then
speed = speed + 0.5
end

bv.Velocity = script.Parent.CFrame.LookVector * speed
elseif seat.Throttle == -1 then
if speed > -seat.MaxSpeed then
speed = speed
end

bv.Velocity = script.Parent.CFrame.LookVector * speed
end

if seat.Steer == 1 then
bg.CFrame = bg.CFrame * CFrame.fromEulerAnglesXYZ(0, -math.rad(1), 0)
elseif seat.Steer == -1 then
bg.CFrame = bg.CFrame * CFrame.fromEulerAnglesXYZ(0, math.rad(1), 0)
end
end
``````

end

Blockquote

I did this for my boat but it won’t work. It erroring on this part of script.

seat.Changed:Connect(function(Direction)
Any help.
if Direction == “Thtottle” then