I’m trying to make a suspension car. It works, and in studio it’s very responsive, but in the game client there’s a huge delay when steering. I tried to switch the script to a local script but then it doesn’t drive at all. I also tried setting network ownership, but it didn’t make any difference.
Server script:
-- get the specifications
local speed = script.speed.Value
local accleration = script.acceleration.Value
local steeringspeed = script.steeringSpeed.Value
local steeringangle = script.steeringAngle.Value
-- set up the shortcuts
local vehicle = script.Parent.Parent
local seat = script.Parent
-- find the tires
local A = vehicle.A -- front left
local AA = vehicle.AA -- front right
local B = vehicle.B -- back left
local BB = vehicle.BB -- back right
-- find the steering mechanism
local steerA = vehicle.SteeringA.Servo
local steerB = vehicle.SteeringB.Servo
-- set up wheels' motor accerlation
A.Motor.MotorMaxTorque = accleration
AA.Motor.MotorMaxTorque = accleration
B.Motor.MotorMaxTorque = accleration
BB.Motor.MotorMaxTorque = accleration
local VehicleSeat = script.Parent
VehicleSeat.Changed:Connect(function(prop)
if prop == "Occupant" then
local humanoid = VehicleSeat.Occupant
if humanoid then
local player = game:GetService("Players"):GetPlayerFromCharacter(humanoid.Parent)
if player then
VehicleSeat:SetNetworkOwner(player)
end
else
VehicleSeat:SetNetworkOwnershipAuto()
end
end
end)
while true do
-- power the wheels
velocity = seat.Throttle * speed -- use the seat's throttle to determine the wheels' action (backward? forward? nothing?)
A.Motor.AngularVelocity = velocity
AA.Motor.AngularVelocity = velocity
B.Motor.AngularVelocity = -velocity
BB.Motor.AngularVelocity = -velocity
wait()
-- steering
steering = seat.Throttle * speed
steerA.AngularSpeed = steeringspeed
steerA.ServoMaxTorque = 100000000
steerA.TargetAngle = steeringangle*seat.Steer
steerB.AngularSpeed = steeringspeed
steerB.ServoMaxTorque = 100000000
steerB.TargetAngle = steeringangle*seat.Steer
end
Vehicle movement such as steering and acceleration should be all handled on the client. The only time the server comes in is when you do checks for speed hacks, teleporting vehicles, customization, tuning etc.
Setting the network owner to the client will not do anything if the server is still responsible for turning the wheels.
This may be the issue. Converting code in a normal script is not as simple as moving all the code to a local script. Not all API, Properties, Objects etc. that are on the server are available locally. It’s sometimes much more complicated than that.
I cannot provide any further solutions as the code you provided is pretty limited.
Sorry, I meant that it may require a full inspection of all the scripts of the vehicle to actually identify where the problem is. In the code you provided above, the only issue I see is using :SetNetworkOwner because this is only available to the server, not locally. Aside from that, the code above should work on a local script, so the issue may be somewhere else.
--services
local Workspace = game:GetService("Workspace")
-- get the specifications
local speed = script.speed.Value
local accleration = script.acceleration.Value
local steeringspeed = script.steeringSpeed.Value
local steeringangle = script.steeringAngle.Value
-- set up the shortcuts
local vehicle = Workspace:WaitForChild("Vehicle") --change "Vehicle" to the name of the vehicle model
local seat = vehicle:WaitForChild("Seat") --change "Seat" to the name of the driver seat
-- find the tires
local A = vehicle.A -- front left
local AA = vehicle.AA -- front right
local B = vehicle.B -- back left
local BB = vehicle.BB -- back right
-- find the steering mechanism
local steerA = vehicle.SteeringA.Servo
local steerB = vehicle.SteeringB.Servo
-- set up wheels' motor accerlation
A.Motor.MotorMaxTorque = accleration
AA.Motor.MotorMaxTorque = accleration
B.Motor.MotorMaxTorque = accleration
BB.Motor.MotorMaxTorque = accleration
local VehicleSeat = script.Parent
while true do
-- power the wheels
velocity = seat.Throttle * speed -- use the seat's throttle to determine the wheels' action (backward? forward? nothing?)
A.Motor.AngularVelocity = velocity
AA.Motor.AngularVelocity = velocity
B.Motor.AngularVelocity = -velocity
BB.Motor.AngularVelocity = -velocity
wait()
-- steering
steering = seat.Throttle * speed
steerA.AngularSpeed = steeringspeed
steerA.ServoMaxTorque = 100000000
steerA.TargetAngle = steeringangle*seat.Steer
steerB.AngularSpeed = steeringspeed
steerB.ServoMaxTorque = 100000000
steerB.TargetAngle = steeringangle*seat.Steer
end
Normal Script in ServerScriptService:
local vehicle = Workspace:WaitForChild("Vehicle") --change "Vehicle" to the name of the vehicle model
local seat = vehicle:WaitForChild("Seat") --change "Seat" to the name of the driver seat
seat.Changed:Connect(function(prop)
if prop == "Occupant" then
local humanoid = VehicleSeat.Occupant
if humanoid then
local player = game:GetService("Players"):GetPlayerFromCharacter(humanoid.Parent)
if player then
VehicleSeat:SetNetworkOwner(player)
end
else
VehicleSeat:SetNetworkOwnershipAuto()
end
end
end)
Give this a try, however read the comments in the code
It’s just a development practice. I don’t like placing local scripts in starter gui or in the backpack. Also, do note that local scripts only work in certain places, local scripts do not run when it is a descendant of the workspace, server script service, etc (player’s character is an exception)
Having multiple copies of one script that does the same thing is not efficient memory wise. You could have one script that has a reference to every vehicle in the game and use a loop to listen to every seats’ event:
local Workspace = game:GetService("Workspace")
local Vehicles = {
Workspace.Vehicle_1,
Workspace.Vehicle_2,
Workspace.Vehicle_3,
}
local function OnSeatChanged(prop)
if prop == "Occupant" then
local humanoid = VehicleSeat.Occupant
if humanoid then
local player = game:GetService("Players"):GetPlayerFromCharacter(humanoid.Parent)
if player then
VehicleSeat:SetNetworkOwner(player)
end
else
VehicleSeat:SetNetworkOwnershipAuto()
end
end
end
for i, v in ipairs(Vehicles) do
v.seat.Changed:Connect(OnSeatChanged)
end
Or if all the vehicles are placed in one folder/model, then you could do this:
local Workspace = game:GetService("Workspace")
local VehiclesContainer = Workpace:WaitForChild("Vehicles")
local function OnSeatChanged(prop)
if prop == "Occupant" then
local humanoid = VehicleSeat.Occupant
if humanoid then
local player = game:GetService("Players"):GetPlayerFromCharacter(humanoid.Parent)
if player then
VehicleSeat:SetNetworkOwner(player)
end
else
VehicleSeat:SetNetworkOwnershipAuto()
end
end
end
for i, v in ipairs(VehiclesContainer:GetChildren()) do
v.seat.Changed:Connect(OnSeatChanged)
end