Vehicle moving slow despite having high velocity

I have a fighter jet in my game, and normally it flies fine. After about 30 minutes to an hour into the server’s lifetime, all of the jets in the game start moving at about 30% their normal speed. I suspect this is because of garbage collection issues (its tycoon game, lots of droppers) that are reducing the heartbeat speed which I will need to fix.

That aside, is there any way I can make this vehicle less affected by this issue?

Summary of script below:

  • line1: function header, function is tied to runService.Heartbeat

  • health mechanics: spin plane and point downward while heath is zero

  • throttle: increase or decrease throttle based on inputs

  • speed increment: gradually increase plane’s speed value to meet throttle

  • ratio calculation: flightspeed is the speed the plane needs to fly. this ratio is determined by how close the plane’s speed is to reaching the flght speed

  • lerp the plane’s velocity to its current speed

  • apply torque based on the flight velocity, and apply direction based on camera direction

  • tilt the plane into the depth of the turn

  • raycast below, if ground is found then deploy the landing gear

  • set engine sound playback speed to the throttle

  • toggle particle effects in the engine based on throttle

  • prevent welded player from gaining networkOwnership of the plane

  • fire the guns if mouse is down

  • refill bombs when empty

local update = function(dt)
	--Health mechanics
	if hitboxHum.Health < hitboxHum.MaxHealth*.4 then
		plane.Engine.Smoke.Enabled = true
	else
		plane.Engine.Smoke.Enabled = false
	end
	
	if hitboxHum.Health == 0 then
		died = true
		
		if plane.PrimaryPart.AssemblyLinearVelocity.Magnitude == 0 then death(false) end
		
		--spin plane
		local x,y,z = mainMotor.C0:ToOrientation()
		mainMotor.C0 = mainMotor.C0:Lerp(CFrame.fromOrientation(0, 0, z + math.pi* 2 * dt), .5)
		
		--give inertia
		--plane.PrimaryPart.BodyGyro.D = 500
		
		--enable fire
		plane.Engine.Explosion.Enabled = true
		
		--max speed
		inputs.W = 1
	end
	
	
	
	
	--throttle
	if inputs.W == 1 then
		throttle = throttle + (dt * throttleIncrement)
		if throttle > 1 and not died then throttle = 1 end
		if occupant then events.UpdateUI:FireClient(occupant, throttle, "throttle") end
	elseif inputs.S == 1 then
		throttle = throttle - (dt * throttleIncrement)
		if throttle < 0 then throttle = 0 end
		if occupant then events.UpdateUI:FireClient(occupant, throttle, "throttle") end
	end
	
	--Speed increment
	local targetSpeed = topSpeed * throttle
	if currentSpeed < targetSpeed then
		--increase speed
		currentSpeed = currentSpeed + (acceleration * dt)
		if currentSpeed > targetSpeed then currentSpeed = targetSpeed end
	elseif currentSpeed > targetSpeed then
		--decrease speed
		currentSpeed = currentSpeed - (acceleration * dt * 2)
		if currentSpeed < targetSpeed then currentSpeed = targetSpeed end
	end
	
	--this ratio is a ratio between the aircraft's current speed and its flight velocity
	local ratio = math.min(currentSpeed/flightVelocity, 1) --flight velocity is the velocity needed for the plane to achieve flight
	local modifiedRatio =  math.max(0, (ratio*2)-1  )
	local mX, mY, mZ = camCF:ToOrientation()
	local mCF = CFrame.fromOrientation(mX * modifiedRatio, mY, mZ * modifiedRatio)
	
	--apply speed
	plane.PrimaryPart.AssemblyLinearVelocity = plane.PrimaryPart.AssemblyLinearVelocity:Lerp(plane.PrimaryPart.CFrame.LookVector * currentSpeed, ratio * ratio)
	
	--apply gyro based on the ratio calculated above
	plane.PrimaryPart.AlignOrientation.MaxTorque = (2*planeMass * ratio * ratio)^2
	
	--rotate plane
	plane.PrimaryPart.AlignOrientation.CFrame = plane.PrimaryPart.AlignOrientation.CFrame:Lerp(mCF, topTurnSpeed * math.min(dt, .015) * ratio * ratio)
	
	--get rotational difference components
	local diffX, diffY = (camCF * plane.PrimaryPart.CFrame:Inverse()):ToOrientation()
	
	--Tilt the plane to the depth of the turn
	if not died then
		local Tilt = CFrame.fromEulerAnglesXYZ(0, 0, diffY * .5)
		mainMotor.C0 = mainMotor.C0:Lerp(Tilt, 5 * dt * modifiedRatio * modifiedRatio)
	end
	
	--landing gear
	local params = RaycastParams.new()
	params.FilterDescendantsInstances = {char, plane, hitboxModel, game.Workspace.Projectiles}
	params.FilterType = Enum.RaycastFilterType.Exclude
	local results = workspace:Raycast(plane.PrimaryPart.Position, Vector3.yAxis*-80, params)
	
	if results and currentSpeed < topSpeed/2 then script:SetAttribute("Landing", true) else script:SetAttribute("Landing", false) end
	
	
	--engine sound
	plane.Engine.Run.PlaybackSpeed = math.min( .8 + throttle * .4, 1.2)
	
	
	--engine effects
	if throttle > 0 then
		engineEffects.Left.Smoke.Emit.Enabled = true
		engineEffects.Right.Smoke.Emit.Enabled = true
		if throttle > .9 then
			engineEffects.Left.Flame.Emit.Enabled = true
			engineEffects.Right.Flame.Emit.Enabled = true
		else
			engineEffects.Left.Flame.Emit.Enabled = false
			engineEffects.Right.Flame.Emit.Enabled = false
		end
	else
		engineEffects.Left.Smoke.Emit.Enabled = false
		engineEffects.Right.Smoke.Emit.Enabled = false
	end
	
	
	--ownership
	plane.PrimaryPart:SetNetworkOwner(nil)
	
	
	
	
	--firing
	if inputs.M1 == 1 and occupant and lastFire + firerate < tick() then
		for _, v in pairs(plane.Guns:GetChildren()) do
			lastFire = tick()
			

			local StartCF = v.CFrame
			local spreadCF = CFrame.fromOrientation(math.rad(math.random(-spread * 10, spread * 10)/10), math.rad(math.random(-spread * 10, spread * 10)/10), 0 )
			StartCF = StartCF * spreadCF


			local projectileParams = require(pStats.ProjectileParams)

			projectileParams.StartTime = tick()
			projectileParams.StartCF = StartCF
			projectileParams.Caster = v
			projectileParams.ModelsBlacklist = {char, script.Parent, hitboxModel}
			projectileParams.ToolTip = script.Parent.Name .. " - Autocannon"
			projectileParams.InheritedVelocity = plane.PrimaryPart.AssemblyLinearVelocity

			game.ReplicatedStorage.Remotes.FireProjectile:Fire(occupant, projectileParams)
		end
	end
	
	
	--bombs
	if lastBombRegen + bombRegen < tick() then
		lastBombRegen = tick()
		if bombsReady < bombCapacity then 
			bombsReady = bombsReady + 1 
			script.Parent.Engine.Load:Play()
			if occupant then
				events.UpdateUI:FireClient(occupant, bombsReady, "bombs")
			end
		end
	end
end
4 Likes

I’m having the same problem with trains in a project of mine. I would recommend making your jet models Client-sided, which may help with reducing lag as it is connected differently to the Server system. This helped with me.

I hope you find a good solution! :+1:

try doing * dt * 60 instead
when you only do dt, everything would be 60x slower than if you didn’t do * dt

adding the * 60 should make it not so slow

where are you seeing the * 60 ?

as @cornbeefthief1123 said, try making models client side and just send position data to all clients, it will reduce performance issue, It’s a very bad practice to make things Rendered on the Server. The server should only be used in absolute necessity…

i’m saying add * 60 everytime you do * dt

looks like memory leak, maybe you forget to disconnect function or you don’t properly destroy objects

What kind of sanity checks would you recommend so that hackers dont abuse the client sided control of the vehicle?

Well, on the server you can put sanity checks for like Position and Speed Validation, Boundary Enforcement, A Rate Limit to avoid overload, and Action Verification and Store the Data of the last valid position in the Server and Send it back to the Client if an anomaly is detected so you can reverse to last “safe” location

you only need to care about the data that pass through the server anyway, since it’ll effectively replicate on other clients. Let the Hackers play clientside if it’s Local Data