So I have a script that detects when a player in a boat changes direction, and accounts for it. Using tweenservice, it can go left, right, backwards forwards etc. and has acceleration. One issue it has is then when you turn (via detecting a change in steer), I can’t figure out a way to readjust the velocity of the boat to change in the direction of the rotation change, and the boat can suddenly be going backwards after you turn it.
Here’s my code, could someone help me?
script.Parent.MaxSpeed = script.Parent.Settings.MaxSpeed.Value
local Vehicle = script.Parent.Parent
local VehicleSeat = script.Parent
maxspeed = script.Parent.MaxSpeed
script.Parent.BodyPosition.position = script.Parent.Position
script.Parent.BodyGyro.cframe = script.Parent.CFrame
value1 = 0 --- real time speed
local bv = VehicleSeat:FindFirstChild("BodyVelocity")
local clone = bv:Clone()
local driver = false
local TweenService = game:GetService("TweenService")
local speed_Tween
local turn_Tween
local turny = TweenInfo.new(5)
local speedy = TweenInfo.new(5)
local BodyVel = script.Parent.BodyVelocity
VehicleSeat.Changed:Connect(function()
if speed_Tween ~= nil then
speed_Tween:Cancel()
speed_Tween = nil
end
if turn_Tween ~= nil then
turn_Tween:Cancel()
turn_Tween = nil
end
if VehicleSeat.Throttle == 1 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity=(maxspeed*script.Parent.CFrame.lookVector)})
--script.Parent.BodyVelocity.velocity = script.Parent.CFrame.lookVector*value1
elseif VehicleSeat.Throttle == 0 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity=0*script.Parent.CFrame.lookVector})
elseif VehicleSeat.Throttle == -1 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity=((-maxspeed)*script.Parent.CFrame.lookVector)})
end
if VehicleSeat.Steer == 1 then
turn_Tween = TweenService:Create(script.Parent.BodyGyro, turny, {CFrame=(script.Parent.BodyGyro.cframe * CFrame.fromEulerAnglesXYZ(0,- script.Parent.Settings.TurnSpeed.Value,0))})
if VehicleSeat.Throttle == 1 then
BodyVel.Velocity=(maxspeed*script.Parent.CFrame.lookVector)
elseif VehicleSeat.Throttle == -1 then
BodyVel.Velocity=(-maxspeed*script.Parent.CFrame.lookVector)
end
elseif VehicleSeat.Steer == 0 then
turn_Tween = TweenService:Create(script.Parent.BodyGyro, turny, {CFrame=(script.Parent.BodyGyro.cframe * CFrame.fromEulerAnglesXYZ(0,0,0))})
elseif VehicleSeat.Steer == -1 then
turn_Tween = TweenService:Create(script.Parent.BodyGyro, turny, {CFrame=(script.Parent.BodyGyro.cframe * CFrame.fromEulerAnglesXYZ(0,script.Parent.Settings.TurnSpeed.Value,0))})
if VehicleSeat.Throttle == 1 then
BodyVel.Velocity=(maxspeed*script.Parent.CFrame.lookVector)
elseif VehicleSeat.Throttle == -1 then
BodyVel.Velocity=(-maxspeed*script.Parent.CFrame.lookVector)
end
end
if speed_Tween then
speed_Tween:Play()
end
if turn_Tween then
turn_Tween:Play()
end
if script.Parent.Position.Y > script.Parent.BodyPosition.Position.Y then
script.Parent.Driving.Value = false
value1 = 0
script.Parent.BodyVelocity.velocity = script.Parent.CFrame.lookVector*value1
end
end)
The BodyGyro won’t slow down your velocity in a given direction; if you want to apply the rotation to the velocity vector, you need to tween the velocity vector along with the gyro, too.
That would mean you need to cancel the speed_tween and reset it to tween to the same max velocity, but in the same direction as your body gyro orientation.
Okay before I suggest a solution (I have a few in mind) I need to know, how does .Changed get called? Is it based on position changing? That would be good to know, I don’t really have any experience with seats.
Okay then I think I know how to deal with it. Here’s the explanation:
Since you can only detect when the player changes directions, let’s say you make the BodyGyro tween for 5 seconds, as you have it. Because of this, you should also tween the velocity to the same direction; how much you delay that is up to you if you want a gliding effect or if you want to be as responsive as possible.
Next you need to set up an event for Tween:Completed (I think that’s the syntax, search it up just in case). The reason for this is because if someone holds left for more than 5 seconds, you won’t get a VehicleSeat.Changed event so you won’t be able to reset the Tween to keep turning. Thus you need the Completed event to reapply the same Tween that you used initially, for both the Gyro and the Velocity objects.
And that should do it, try it and see what happens. Good luck!
Before, you were using the lookvector for the velocity tween. But now you should use the look vector that the gyro uses, still applying the same magnitude speed multiplier to it.
if VehicleSeat.Throttle == 1 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity=(maxspeed*script.Parent.CFrame.lookVector)})
--script.Parent.BodyVelocity.velocity = script.Parent.CFrame.lookVector*value1
elseif VehicleSeat.Throttle == 0 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity=0*script.Parent.CFrame.lookVector})
elseif VehicleSeat.Throttle == -1 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity=((-maxspeed)*script.Parent.CFrame.lookVector)})
end
This here should be dealt with after you check if you are turning. Otherwise you will end up rewriting speed_Tween for no reason.
For your body velocity, it should look like this
-- Here's your body gyro code for Steer == 1:
turn_Tween = TweenService:Create(script.Parent.BodyGyro, turny, {CFrame=(script.Parent.BodyGyro.cframe * CFrame.fromEulerAnglesXYZ(0,- script.Parent.Settings.TurnSpeed.Value,0))})
-- Here's what your body velocity should be if Throttle == 1:
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity= maxspeed*(script.Parent.BodyGyro.cframe * CFrame.fromEulerAnglesXYZ(0,- script.Parent.Settings.TurnSpeed.Value,0)).LookVector})
You should modify the remaining code using this construct. All it is doing is setting the velocity in the direction of the look vector, while also applying the multiplier maxspeed. For the remaining cases, you just deal with negative signs.
script.Parent.MaxSpeed = script.Parent.Settings.MaxSpeed.Value
local Vehicle = script.Parent.Parent
local VehicleSeat = script.Parent
maxspeed = script.Parent.MaxSpeed
script.Parent.BodyPosition.position = script.Parent.Position
script.Parent.BodyGyro.cframe = script.Parent.CFrame
value1 = 0 --- real time speed
local bv = VehicleSeat:FindFirstChild("BodyVelocity")
local clone = bv:Clone()
local driver = false
local TweenService = game:GetService("TweenService")
local speed_Tween
local turn_Tween
local turny = TweenInfo.new(5)
local speedy = TweenInfo.new(5)
local BodyVel = script.Parent.BodyVelocity
VehicleSeat.Changed:Connect(function()
if speed_Tween ~= nil then
speed_Tween:Cancel()
speed_Tween = nil
end
if turn_Tween ~= nil then
turn_Tween:Cancel()
turn_Tween = nil
end
if VehicleSeat.Steer == 1 then
turn_Tween = TweenService:Create(script.Parent.BodyGyro, turny, {CFrame=(script.Parent.BodyGyro.cframe * CFrame.fromEulerAnglesXYZ(0,- script.Parent.Settings.TurnSpeed.Value,0))})
if VehicleSeat.Throttle == 1 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity= maxspeed*(script.Parent.BodyGyro.cframe * CFrame.fromEulerAnglesXYZ(0,- script.Parent.Settings.TurnSpeed.Value,0)).LookVector})
elseif VehicleSeat.Throttle == -1 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity= -maxspeed*(script.Parent.BodyGyro.cframe * CFrame.fromEulerAnglesXYZ(0,- script.Parent.Settings.TurnSpeed.Value,0)).LookVector})
end
elseif VehicleSeat.Steer == 0 then
turn_Tween = TweenService:Create(script.Parent.BodyGyro, turny, {CFrame=(script.Parent.BodyGyro.cframe * CFrame.fromEulerAnglesXYZ(0,0,0))})
elseif VehicleSeat.Steer == -1 then
turn_Tween = TweenService:Create(script.Parent.BodyGyro, turny, {CFrame=(script.Parent.BodyGyro.cframe * CFrame.fromEulerAnglesXYZ(0,script.Parent.Settings.TurnSpeed.Value,0))})
if VehicleSeat.Throttle == 1 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity= maxspeed*(script.Parent.BodyGyro.cframe * CFrame.fromEulerAnglesXYZ(0,script.Parent.Settings.TurnSpeed.Value,0)).LookVector})
elseif VehicleSeat.Throttle == -1 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity= -maxspeed*(script.Parent.BodyGyro.cframe * CFrame.fromEulerAnglesXYZ(0, script.Parent.Settings.TurnSpeed.Value,0)).LookVector})
end
end
if not speed_Tween then
if VehicleSeat.Throttle == 1 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity=(maxspeed*script.Parent.CFrame.lookVector)})
--script.Parent.BodyVelocity.velocity = script.Parent.CFrame.lookVector*value1
elseif VehicleSeat.Throttle == 0 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity=0*script.Parent.CFrame.lookVector})
elseif VehicleSeat.Throttle == -1 then
speed_Tween = TweenService:Create(BodyVel, speedy, {Velocity=((-maxspeed)*script.Parent.CFrame.lookVector)})
end
end
if speed_Tween then
speed_Tween:Play()
end
if turn_Tween then
turn_Tween:Play()
end
if script.Parent.Position.Y > script.Parent.BodyPosition.Position.Y then
script.Parent.Driving.Value = false
value1 = 0
script.Parent.BodyVelocity.velocity = script.Parent.CFrame.lookVector*value1
end
end)
What does this line do? It’s nested in your if statement at the end. If you are resetting the position during the Tween then it’s probably why it’s still clunky.