# Make this boat move

Hello! So I am making a horror game and I have a boat in the game that moves smoothly in this path. The thing is I have no clue how to make the boat move smoothly itself while the player is seating in the chair.

I have tried teleporting the boat but that’s not smooth and I want it smooth and slow as possible.

Example:

1 Like

You can use TweenService to tween the boat from Point1to Point2, or you can use CFrames and Lerp() smoothly to a position.

I recommend you using TweenService to ween the boat. You can watch a tutorial online or use this tutorial TweenService tutorial

There are 3 ways I can think of:

`TweenService`
As @cheesy_roblox190 said, Tween the Boat from A to B, If you want a more Linear way of doing it, Use `CFrame:Lerp()` for this.

``````Info = TweenInfo.new( -- Stuff for the Tween to Apply
1, -- Duration
Enum.EasingStyle.Sine, -- Transition
Enum.EasingDirection.Out, -- Transition Type
0, -- Times Repeated?
false, -- Reversed?
0 -- Delay
)
TweenService:Create(PrimaryPart, Info, {Position = YourPosition}):Play()
``````

`CFrame:Lerp()`
This is a Linear way of doing it, almost the same as `TweenService`

``````for i = 0,100,.01 do
wait() -- used for a slower effect
PrimaryPart.CFrame:Lerp(PointB.CFrame, i) -- i = Percentage Completed
-- for each iteration, the Item will advance
end
``````

for the `i` part, each time the iteration is completed, `i` will add up, since we have it at `.01 (1/100)` it will add `.01`, which in turn will make it slow, and maybe smooth

`Velocity`
Apply a Velocity to the Boat to move towards a position

``````while true do
PrimaryPart.AssemblyLinearVelocity = PrimaryPart.CFrame.LookVector * 20
-- Applies a Velocity based on the way the Part is looking
end
``````
1 Like

Velocity imo atleast would be the smoothest and easiest as it’s mostly physics based. CFrame and Lerp often look robotic/

3 Likes

how would I be able to check if the player sat on the boat?

The the `Occupant` of the `Seat`, if its `nil`, nobody is sitting in it, Use `Changed`, or `GetPropertChangedSignal` for the Seat.

``````Seat:GetPropertyChangedSignal("Occupant"):Connect(function()
if Seat.Occupant then
print"Seat Occupied"
else
print"Seat Vacant"
end
end)

``````

also I wanted the boat to have a couple turns how would I do that? By adding more tweens?

I guess you could tween the CFrame to where you want it to look.
If you use lerp it changes the orientation to the goal’s CFrame orientation.

You can also use CFrame.lookAt but won’t be smooth unless you tween it.
Sorry if I’m bad at explaining.

I would read about CFrames to if you dont understand this CFrame Document

If you tween the CFrame (on the server) it will be choppy and not smooth. Instead, you should tween the position/cframe of an AlignPosition and an AlignOrientation. These two instances combined work just like setting the cframe (when they are set to use enough force) but they use physics to do so, which causes the client to smooth out the motion.

I got a little carried away and programmed this:

``````-- The speed of the boat
local SPEED = 10

local boat = script.Parent
-- When you make a new boat make sure to set the AlignPosition and AlignOrientation to the CFrame where you want the boat
local alignPosition = boat.PrimaryPart.AlignPosition
alignPosition.Position = boat.PrimaryPart.Position
local alignOrientation = boat.PrimaryPart.AlignOrientation
alignOrientation.CFrame = boat.PrimaryPart.CFrame

-- A list of seats to trigger the boat moving
local seats = {
boat.SeatOne;
}

local pathPart = workspace.PathPart-- Set to a part with attachments named "1", "2", "3" etc. which represent the path of the boat

local hasStarted = false
local function startBoat()
-- Only start the boat when someone sits for the first time
if hasStarted then
return
end
hasStarted = true

print("Boat starting path!")

-- Instead of tweening boat cframe, tween CFrame value so we can update the boat cframe with the mover constraints
local goalCFrameValue = Instance.new("CFrameValue")
goalCFrameValue.Value = boat.PrimaryPart.CFrame
goalCFrameValue.Parent = boat.PrimaryPart

-- Update the align position and align orientation
local function onGoalChanged()
alignOrientation.CFrame = goalCFrameValue.Value
alignPosition.Position = goalCFrameValue.Value.Position
end

-- Update the align position and align orientation when the CFrame value is changed
onGoalChanged()
goalCFrameValue.Changed:Connect(function()
onGoalChanged()
end)

-- Go through each attachment, make and play a tween, go to the next attachment when the tween is done
local currentIndex = 1
local pathAttachment = pathPart:FindFirstChild(tostring(currentIndex))

while pathAttachment do
local newCframe = pathAttachment.WorldCFrame
local oldCframe = goalCFrameValue.Value

local distance = (newCframe.Position - oldCframe.Position).Magnitude

local tweenInfo = TweenInfo.new(distance/SPEED, Enum.EasingStyle.Linear)
local tween = game:GetService("TweenService"):Create(goalCFrameValue, tweenInfo, {Value = newCframe})
tween:Play()
tween.Completed:Wait()

currentIndex += 1
pathAttachment = pathPart:FindFirstChild(tostring(currentIndex))
end

print("Boat finished path!")
-- Boat finished path, maybe destroy in a few seconds or something
end

-- Run the start boat function whenever someone sits (startBoat has a debounce so it only can start once)
for _, seat in ipairs(seats) do
seat:GetPropertyChangedSignal("Occupant"):Connect(startBoat)
end
``````

Here is a place file that demonstrates how the code works:

Smooth Path Boat.rbxl (38.3 KB)

1 Like

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