I didn’t really know WHAT to call this, because I’ve never seen anything quite like it. I don’t know what causes it, all I know is that it’s client side (It only happens to the player who owns the vehicle). Basically, whenever this feels like happening (I can’t get it to consistently happen), the player who owns the vehicle can not move the vehicle anymore, but there’s no errors or anything in the console, and the script cant be completely busted because the “press E to sit” thing still works just fine and it’s part of the same event. Also, whenever the player is not in the vehicle and they touch said vehicle, the player and the vehicle can dissapear for a few moments, and when you reappear, your movement is super buggy and laggy for a couple seconds.
Here’s a video demonstrating what this bug does:
Server script:
local serverEvents = game.ServerStorage.Events
local clientEvents = game.ReplicatedStorage.Events
local vehicle = script.Parent
local owner = vehicle.Owner.Value or vehicle.Owner.Changed:Wait()
local fireRate = vehicle.Firerate.Value
local seats = vehicle.Seats
local vehicleSeat = seats.VehicleSeat
local base = vehicle.Base
local hullParts = {}
for _, part in pairs(vehicle:GetDescendants()) do
if part.Name == "ColorPart" then
table.insert(hullParts, part)
end
end
local hullNumber = #hullParts
local maxHealth = vehicle.MaxHealth.Value
local health = vehicle.Health
local currentHealth = maxHealth
local smoke = vehicle.SmokePart.Smoke
local fire = vehicle.SmokePart.Fire
local rightTrack = vehicle.RightTrack
local leftTrack = vehicle.LeftTrack
local rightMotors = {}
local leftMotors = {}
local wheels = {}
local physicsService = game:GetService("PhysicsService")
local muzzle = vehicle.Turret.Gun.Muzzle
local maxTorque = vehicle.Torque.Value
local maxSpeed = vehicle.Speed.Value
local minDamage = vehicle.MinDamage.Value
local maxDamage = vehicle.MaxDamage.Value
local healthPerPart = math.ceil(maxHealth/hullNumber)
local tags = {}
local damagedParts = {}
local listeners = {}
local currentHealth = health.Value
local despawnTick = tick()
local running = false
local gunGyro = vehicle.Turret.Gun.Base.BodyGyro
local collisionGroup1 = "Hull"
local collisionGroup2 = "Wheels"
local loaded = vehicle.Loaded
gunGyro.CFrame = gunGyro.Parent.CFrame
for _, wheel in pairs(rightTrack:GetChildren()) do
if wheel.Name == "Wheel" then
table.insert(rightMotors, wheel.WheelAxle.HingeConstraint)
table.insert(wheels, wheel.Wheel.Hitbox)
end
end
for _, wheel in pairs(leftTrack:GetChildren()) do
if wheel.Name == "Wheel" then
table.insert(leftMotors, wheel.WheelAxle.HingeConstraint)
table.insert(wheels, wheel.Wheel.Hitbox)
end
end
for _, part in pairs(hullParts) do
physicsService:SetPartCollisionGroup(part, collisionGroup1)
end
for _, part in pairs(wheels) do
physicsService:SetPartCollisionGroup(part, collisionGroup2)
end
physicsService:CollisionGroupSetCollidable(collisionGroup1, collisionGroup2, false)
local function stop()
for _, motor in pairs(rightMotors) do
motor.AngularVelocity = 0
end
for _, motor in pairs(leftMotors) do
motor.AngularVelocity = 0
end
base.Running:Stop()
end
local function startUp()
running = true
base.Running:Play()
end
health.Changed:Connect(function(new)
local damageRatio = 1 - new/maxHealth
fire.Enabled = damageRatio >= 0.8
smoke.Enabled = damageRatio >= 0.5
smoke.Rate = damageRatio * 80 - 35
smoke.Speed = NumberRange.new(damageRatio * 3, damageRatio * 5)
if new < currentHealth then
while (maxHealth - healthPerPart * #damagedParts) - new > healthPerPart do
local part = hullParts[math.random(1, hullNumber)]
if not table.find(damagedParts, part) then
part.Material = Enum.Material.CorrodedMetal
table.insert(damagedParts, part)
end
end
elseif new > currentHealth then
while (maxHealth - healthPerPart * (#damagedParts - 1)) - new < healthPerPart do
local part = hullParts[math.random(1, hullNumber)]
local toRemove = table.find(damagedParts, part)
if toRemove then
part.Material = Enum.Material.Metal
table.remove(damagedParts, toRemove)
end
end
end
currentHealth = new
if new <= 0 then
stop()
for _, seat in pairs(seats:GetChildren()) do
seat.Disabled = false
seat.ProximityAttachment.ProximityPrompt.Enabled = false
if seat.Occupant then
seat.Occupant.Sit = false
end
end
vehicle:BreakJoints()
base.Explosion:Play()
wait(2.5)
if vehicle and vehicle.Parent then
vehicle:Destroy()
vehicle = nil
end
end
end)
vehicle.Fire.OnServerEvent:Connect(function(_, rayHit, position)
if loaded.Value then
loaded.Value = false
clientEvents.TankFire:FireAllClients(owner, muzzle)
serverEvents.TankFire:Fire(owner, rayHit, position)
wait(4.5)
loaded.Value = true
end
end)
for _, seat in pairs(seats:GetChildren()) do
seat:GetPropertyChangedSignal("Occupant"):Connect(function(new)
if not seat.Occupant and vehicle and vehicle.Parent then
seat.Disabled = true
seat.ProximityAttachment.ProximityPrompt.Enabled = true
end
end)
if seat == vehicleSeat then
seat.ProximityAttachment.ProximityPrompt.Triggered:Connect(function(player)
local humanoid = player.Character.Humanoid
if ((seat == vehicleSeat and player == owner) or seat ~= vehicleSeat) and humanoid.Health > 0 and not humanoid.Sit then
seat:Sit(player.Character.Humanoid)
seat.Disabled = false
seat.ProximityAttachment.ProximityPrompt.Enabled = false
for _, part in pairs(vehicle:GetDescendants()) do
if part:IsA("BasePart") then
part:SetNetworkOwner(owner)
end
end
local localScript = script.LocalVehicleScript:Clone()
localScript.Parent = player.PlayerGui
localScript.Disabled = false
local function shutdown()
for _, part in pairs(vehicle:GetDescendants()) do
if part:IsA("BasePart") then
part:SetNetworkOwnershipAuto()
end
end
gunGyro.CFrame = gunGyro.Parent.CFrame
despawnTick = tick()
running = false
for _, listener in pairs(listeners) do
listener:Disconnect()
end
listeners = {}
stop()
end
listeners[1] = humanoid.Seated:Connect(function(new)
if not new then
player.Character.HumanoidRootPart.CFrame = vehicleSeat.CFrame * CFrame.new(0, 13, 0)
shutdown()
end
end)
listeners[2] = humanoid.Died:Connect(shutdown)
startUp()
end
end)
else
seat.ProximityAttachment.ProximityPrompt.Triggered:Connect(function(player)
local humanoid = player.Character.Humanoid
if ((seat == vehicleSeat and player == owner) or seat ~= vehicleSeat) and humanoid.Health > 0 and not humanoid.Sit then
seat:Sit(humanoid)
seat.Disabled = false
seat.ProximityAttachment.ProximityPrompt.Enabled = false
end
end)
end
end
for _, motor in pairs(rightMotors) do
motor.MotorMaxTorque = maxTorque
end
for _, motor in pairs(leftMotors) do
motor.MotorMaxTorque = maxTorque
end
vehicle.AncestryChanged:Connect(function()
if not vehicle:IsDescendantOf(game) then
for _, listener in pairs(listeners) do
listener:Disconnect()
end
listeners = nil
end
end)
while vehicle:IsDescendantOf(game) do
if not running and tick() - despawnTick >= 300 then
vehicle:Destroy()
break
end
wait(0.5)
end
Local script:
local player = game.Players.LocalPlayer
local runService = game:GetService("RunService")
local contextActionService = game:GetService("ContextActionService")
local userInputService = game:GetService("UserInputService")
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local vehicleSeat = humanoid.SeatPart
local vehicle = vehicleSeat:FindFirstAncestor("Vehicle")
local base = vehicle.Base
local health = vehicle.Health
local rightTrack = vehicle.RightTrack
local leftTrack = vehicle.LeftTrack
local rightMotors = {}
local leftMotors = {}
local turn = 0.2
local currentVelocity = 0
local mouse = player:GetMouse()
local camera = workspace.CurrentCamera
local gunBase = vehicle.Turret.Gun.Base
local gunGyro = gunBase.BodyGyro
local muzzle = vehicle.Turret.Gun.Muzzle
local enabled = true
local down = false
local mobile = false
local fireRate = vehicle.Firerate.Value
local jumpButton = player:FindFirstChild("JumpButton", true)
local crosshair = game.ReplicatedStorage.Assets.VehicleCrosshair:Clone()
local mobileCrosshair = vehicle.MobileCrosshair:Clone()
local maxSpeed = vehicle.Speed.Value
local tireRadius = vehicle.TireRadius.Value
local realigning = false
local alignTimer = tick()
local alignTime = 2
local vehicleFilter = RaycastParams.new(); vehicleFilter.FilterType = Enum.RaycastFilterType.Whitelist; vehicleFilter.FilterDescendantsInstances = {workspace.Terrain}
local gunFilter = RaycastParams.new(); gunFilter.FilterType = Enum.RaycastFilterType.Blacklist; gunFilter.FilterDescendantsInstances = {vehicle, character, workspace.Barrier}
local loaded = vehicle.Loaded
camera.CameraSubject = vehicle.CameraPart
mouse.Icon = "rbxassetid://6041882539"
crosshair.Parent = player:FindFirstChild("GUI", true)
for _, wheel in pairs(rightTrack:GetChildren()) do
table.insert(rightMotors, wheel:FindFirstChildWhichIsA("HingeConstraint", true))
end
for _, wheel in pairs(leftTrack:GetChildren()) do
table.insert(leftMotors, wheel:FindFirstChildWhichIsA("HingeConstraint", true))
end
local function setMotorVelocity()
local rightVelocity = -currentVelocity
local leftVelocity = currentVelocity
if vehicleSeat.SteerFloat ~= 0 then
rightVelocity = rightVelocity + maxSpeed * vehicleSeat.SteerFloat * (vehicleSeat.ThrottleFloat < 0 and -turn or turn)
leftVelocity = leftVelocity + maxSpeed * vehicleSeat.SteerFloat * (vehicleSeat.ThrottleFloat < 0 and -turn or turn)
end
for _, motor in pairs(rightMotors) do
motor.AngularVelocity = rightVelocity
end
for _, motor in pairs(leftMotors) do
motor.AngularVelocity = leftVelocity
end
end
vehicleSeat:GetPropertyChangedSignal("ThrottleFloat"):Connect(function()
if health.Value > 0 and not realigning then
currentVelocity = vehicleSeat.ThrottleFloat ~= 0 and maxSpeed * vehicleSeat.ThrottleFloat / tireRadius or 0
setMotorVelocity()
end
end)
vehicleSeat:GetPropertyChangedSignal("SteerFloat"):Connect(function()
if health.Value > 0 and not realigning then
setMotorVelocity()
end
end)
contextActionService:BindAction("Fire", function(_, inputState)
if inputState == Enum.UserInputState.Begin then
down = true
if enabled and down and humanoid.Health > 0 then
if not loaded.Value then
loaded.Changed:Wait()
end
enabled = false
while down and humanoid.Health > 0 do
game.ReplicatedStorage.Events.LocalSound:Fire(nil, "TankFire", muzzle.Position)
muzzle.FireEffect1:Emit(100)
muzzle.FireEffect2:Emit(100)
muzzle.SmokeEffect:Emit(100)
local result = workspace:Raycast(muzzle.Position, muzzle.CFrame.RightVector * -5000, gunFilter)
if result then
vehicle.Fire:FireServer(result.Instance, result.Position)
end
coroutine.resume(coroutine.create(function()
muzzle.Recoil.Force = muzzle.CFrame.RightVector * 1500000
wait()
muzzle.Recoil.Force = Vector3.new(0, 0, 0)
end))
if not loaded.Changed:Wait() then
loaded.Changed:Wait()
end
end
enabled = true
end
else
down = false
end
end, true, Enum.UserInputType.MouseButton1, Enum.KeyCode.ButtonR1)
contextActionService:SetTitle("Fire", "Fire")
if jumpButton and userInputService.TouchEnabled and not userInputService.MouseEnabled then
mobile = true
local fireButton = contextActionService:GetButton("Fire")
local paddingX = math.abs(jumpButton.Position.X.Offset) - jumpButton.AbsoluteSize.X
local paddingY = math.abs(jumpButton.Position.Y.Offset) - jumpButton.AbsoluteSize.Y
fireButton.ActionTitle.Font = Enum.Font.TitilliumWeb
fireButton.ActionTitle.TextStrokeTransparency = 0.4
fireButton.Size = jumpButton.Size
fireButton.ActionTitle.TextSize = fireButton.AbsoluteSize.Y * 0.4
fireButton.Position = UDim2.new(1, -(paddingX + fireButton.AbsoluteSize.X), 1, -(paddingY + jumpButton.AbsoluteSize.Y + fireButton.AbsoluteSize.Y + 10))
mobileCrosshair.Parent = player:FindFirstChild("GUI", true)
end
runService:BindToRenderStep("Aim", 100, function()
local endPosition = mouse.hit.p
if mobile then
local unitRay = camera:ScreenPointToRay(crosshair.AbsolutePosition.X + crosshair.AbsoluteSize.X/2, crosshair.AbsolutePosition.Y + crosshair.AbsoluteSize.Y/2)
local hit, hitPosition = workspace:FindPartOnRay(Ray.new(unitRay.Origin, unitRay.Direction * 5000), character)
endPosition = hitPosition
end
gunGyro.CFrame = CFrame.new(gunBase.Position, endPosition)
local result = workspace:Raycast(muzzle.Position, muzzle.CFrame.RightVector * -5000, gunFilter)
if result then
local vector, onScreen = camera:WorldToViewportPoint(result.Position)
crosshair.Visible = onScreen
crosshair.Position = UDim2.fromOffset(vector.X, vector.Y)
end
end)
local function disableTank()
mouse.Icon = ""
crosshair:Destroy()
mobileCrosshair:Destroy()
camera.CameraSubject = humanoid
runService:UnbindFromRenderStep("Aim")
contextActionService:UnbindAction("Fire")
game.ReplicatedStorage.Events.RemoveVehicleScript:FireServer()
script.Disabled = true
end
humanoid.Seated:Connect(function(sitting, seat)
if not sitting then
disableTank()
end
end)
humanoid.Died:connect(function()
disableTank()
end)
while health.Value > 0 do
local result = workspace:Raycast(base.Position, base.CFrame.UpVector * -30, vehicleFilter)
if not result then
realigning = true
setMotorVelocity()
local bodyGyro = Instance.new("BodyGyro")
bodyGyro.CFrame = CFrame.new(0, 0, 0)
bodyGyro.MaxTorque = Vector3.new(0, 0, math.huge)
bodyGyro.P = 5000
bodyGyro.Parent = base
wait(2)
bodyGyro:Destroy()
realigning = false
end
wait(1)
end
Any help with this would be greatly appreciated, as I am completely stumped as to what could be causing this behavior. Thanks!