I have no idea how to fix this bizarre glitch with jets in my game

I’ve tried making new jet systems. I’ve tried editing the original one that was problematic with five different “fixes,” none of which changed anything.

I have the most bizarre glitch I have ever experienced in my game, as it only affects other clients in the game; in the server itself, there were no glitches.

Basically in this glitch, if a player is flying a plane, controlled by this very simple local script:

local seat = script:WaitForChild("this")
local connection = seat.Value
local USINS=game:getService("UserInputService")
local player=game.Players.LocalPlayer
local speed = 150
local maxspeed = 300
local minspeed = 0
local Mouse = player:GetMouse()
local fly = connection.Parent:WaitForChild("fly")
local gyro = connection.Parent.Engine.BodyGyro
local velo = connection.Parent.Engine.BodyVelocity
if connection.Parent ~= nil then
	while fly.Value == true do
		game["Run Service"].RenderStepped:wait(.1)
		if velo.MaxForce == Vector3.new(math.huge,math.huge,math.huge) and not USINS:GetFocusedTextBox() then
			Mouse.TargetFilter = game.Workspace
			local BankAngle = GetBankAngle(Mouse)
			gyro.cframe = (Mouse.Hit*CFrame.Angles(0,0,BankAngle))
			velo.velocity = (connection.Parent.Engine.CFrame.lookVector)*speed
		end	
	end
end

and gets shot down, to all other clients, this is what will appear on their screen:


As you can see, the pilot of the plane is frozen in mid-air; the pilot’s plane continues to fly around.

However, on the pilot’s client, this is his or her view:


And from their view, their character is still alive and inside said jet:

Seems like a simple client-server glitch, right? It gets even weirder…

This is what appears when I looked at the issue from the server in ROBLOX studio:

The pilot in the server is still alive and with his or her plane! This is only an issue for other clients in the game.

I have been struggling with this issue for many months now, and it has been very frustrating to fix. Does anyone know what is happening that is causing this? I have even tried to have the jet’s control system be controlled by server-sided remotes, and this issue only continues to happen.

5 Likes

I don’t know exactly whats going on but it sounds like a local script is controlling the shot down part so it isn’t replicating on the server

The thing that shoots down the jet is a server script, not local one.

Yeah, that is odd behaviour, I look around and see if I can find something

UPDATE ON THIS SITUATION:

I have tried to make the jet movement controlled by the server, one again, with this script scheme:

---client/local script
---include variables from before here
if connection.Parent ~= nil then
	while fly.Value == true do
		game["Run Service"].RenderStepped:wait(.1)
		if velo.MaxForce == Vector3.new(math.huge,math.huge,math.huge) and not USINS:GetFocusedTextBox() then
			Mouse.TargetFilter = game.Workspace
			connection.controls:FireServer("move",Mouse.Hit,Mouse.Hit.p,Mouse.ViewSizeX,Mouse.X)
		end	
	end
end

---server / server script
local engine = script.Parent.Parent:WaitForChild("Engine")
local gyro = engine:WaitForChild("BodyGyro")
local velo = engine:WaitForChild("BodyVelocity")
local m

function GetBankAngle(viewx, x) --This function calculates the Bank Angle
	local VSX,X = viewx,x
	local Ratio = (((VSX/2) - X)/(VSX/2))
	Ratio = (Ratio < -1 and -1 or Ratio > 1 and 1 or Ratio)
	return math.rad(Ratio * 80)
end
script.Parent.controls.OnServerEvent:Connect(function(plr, command, mouse, mPos, xview, x)
	if command == "move" then
		if mouse ~= nil then
			m = mouse
			local BankAngle = GetBankAngle(xview, x)
			gyro.maxTorque = Vector3.new(math.huge,math.huge,math.huge)
			velo.maxForce = Vector3.new(math.huge,math.huge,math.huge)
			gyro.cframe = (mouse*CFrame.Angles(0,0,BankAngle))
			velo.velocity = (engine.CFrame.lookVector)*100
		end
	end
end)

And it keeps happening. Same thing!

This is very odd. I have some ideas in mind that may help and could be the reason for this glitch.

  • How exactly does the shot down script work? Does the script let the client/pilot know that they are being shot down?
  • Does the pilot have full network control of the aircraft? Sometimes Network controlled is owned to server and can create a lot of bugs when it comes to local script that is used by a pilot.
  • Have you tried debugging using prints method? Basically adding prints to some lines of code through the process can help you determine the base point of the cause.

I have other ideas but I would need more info on this.

  1. No, there is nothing of the shot down script that interacts with the pilot’s client.
  2. Hmmm, I forgot about Network Ownership, I should definitely try that.
  3. Yes, I have, but there’s nothing that comes up in output.

I do not think that is the best choice, allowing the server to control the physical motion of the aircraft instead of the pilot/client can create major lag and the latency will not be precise as it can be. Ex. pilot quickly pull back to avoid the collision, that slight delay of the replication and response to the server will be too late.

So would it be better to have the Network Ownership set the player, and keep controls done client side?

1 Like

In that case, here are few suggestions that you should consider.

  • Allow client full control of the aircraft using local scripts to all body movers, but make sure that you allow the server to grant client Network Ownership. Also, RemoteEvent should be used for communication and security.
  • When doing the shot down script, it is highly suggested to place under server script on server side and there are three things to consider when doing so;
    • Pilot Side: I use my mouse to target locked a player or object to be shotdown, RemoteEvent:FireServer() to let the server know that this is the target requested to be shotdown.
    • Other Pilot/Enemy: The other pilot target locked a me (you) to be shotdown, RemoteEvent:FireServer() to let the server know that this is the target requested to be shotdown.
    • Server Side/Gunner: The gunner like you have for example, it will be target locked to any nearby pilot, and use RemoteEvent:FireAllClient(TargetPlayer, …) to let all players and including target player that the target player is being shotdown. Shutdown the flight controls, or whatever you want to do against the player that server do not have control over such as local scripts. Player health damage can be done on server side using TargetPlayer reference.
    • Note: When I say security, it is a communication between player to server. Most of the times, players (“exploiters”) can make false request such I shot down this player from 500 studs away and that is half of the base away. To prevent this, allow player to send the request, but the server will determine the request such as (This is not important to focus yet. This is just for you to be aware once you have solved your problem);
      • Is the pilot within range of the target (ex. 50-100 studs)
      • Is the pilot have a clear target, are there any obstacles in front of the pilot?

I know this may be a lot, but this is the basic standards that you is required to follow in order to achieve proper communication between server and clients. Especially in certain scenerios such as which script should control the shotdown.

I agree with what @SourceShahb is saying. Seems like the problems is in your gun script. Is your shooting script all in a localscript? How is it destroying the object? Does it create an explosion object or what? Anyway, whatever its doing, it should be done by the server not a localscript. Then the server can destroy the target and fire any events to that client if needed.

Screen Shot 2021-05-05 at 2.48.43 AM
As I’ve said before, the script that handles targeting and firing upon jets is a server script.

on = true
ignore_list = {script.Parent}

local runService = game:GetService("RunService")
local owner = script.Parent.team
local Player = game:GetService("Players")

hrp = script.Parent.turret

function findPlayer()
	local highestmag
	local target 
	local t2
	for _,v in ipairs(game.Players:GetChildren()) do
		if on == false then return end
		if v.Character ~= nil and owner.Value ~= nil and v.Team ~= owner.Value and v.Character.Humanoid.Health > 0 then
			if v.Character:FindFirstChild("F-16") or v.Character:FindFirstChild("helicopter") then
				if v.Character.Head ~= nil and (hrp.MAIN.Position - v.Character.Head.Position).magnitude < (highestmag or script.Parent.range.Value) then
					highestmag = (hrp.MAIN.Position - v.Character.Head.Position).magnitude
					target = v
					t2 = target.Character.Head
				end	
			end
		end
	end
	return target and t2 or nil
end

script.Parent.toggle.ClickDetector.MouseClick:connect(function(player)
	--if player.Team ~= Player[owner.Value].Team then return end
	on = not on
	script.Parent.toggle.BrickColor = on and BrickColor.new("Lime green") or BrickColor.new("Really red")
	script.Parent.toggle.Material = on and "Neon" or "SmoothPlastic"
end)

while wait(0.5) do
	if not on then repeat wait(1) until on end
	local target = findPlayer()
	if hrp and target ~= nil then
		--if object.Position.Y >= 14 then
			hrp:SetPrimaryPartCFrame(CFrame.new(hrp.MAIN.CFrame.p, target.CFrame.p))
			local shootfrom = math.random(1,8)
		local hole = script.Parent.turret["b"..shootfrom]
		print("???")
		local ray = Ray.new(hole.CFrame.p, (hole.CFrame.p - target.CFrame.p).unit * 100)
		local part, position = workspace:FindPartOnRayWithIgnoreList(ray, ignore_list, false, true)
		
		local rocket = Instance.new("Part", script.Parent)
		rocket.BrickColor = BrickColor.new("Black")
		rocket.FormFactor = "Custom"
		rocket.Anchored = true
		rocket.Locked = true
		rocket.CanCollide = false
		rocket.Name = "Tracer"
		rocket.Transparency = 0
		rocket.Size = Vector3.new(1,1,3)
		rocket.CFrame = script.Parent.turret.MAIN.CFrame
		rocket.CFrame = CFrame.new(hole.CFrame.p, target.CFrame.p)
		script.Mesh:Clone().Parent = rocket
		
		local dir = CFrame.new(rocket.CFrame.p,rocket.CFrame.p + rocket.CFrame.lookVector).lookVector
			
		rocket.Velocity = dir * 1250
		
		local bf = Instance.new("BodyForce", rocket)
		bf.force = Vector3.new(0, rocket:GetMass() * workspace.Gravity, 0)
		
		rocket.Anchored = false
		
		rocket.Touched:connect(function(hit)
			print("rocket impact: "..hit.Name)
			if hit.Parent.Name:lower() == "turret" then return end
			local ex = Instance.new("Explosion",workspace)
			ex.Position = rocket.Position
			ex.BlastPressure = 10000
			ex.BlastRadius = 7
			ex.Hit:Connect(function(h)
				if h.Parent:FindFirstChild("Humanoid") then
					print("Explosion hit: "..h.Name)
					local creator = Instance.new("ObjectValue",h.Parent.Humanoid)
					local debris = game:GetService("Debris")
					--local plr = game.Players:WaitForChild(owner.Value)
					--if owner and plr then
					--	creator.Value = game.Players[owner.Value]	
					--end
					debris:AddItem(creator,3)
				end
			end)
			local s = Instance.new("Sound",hit)
			s.SoundId = "rbxasset://sounds/collide.wav"
			s.PlayOnRemove = true
			s.Volume = 1
			s:Play()
			rocket:Destroy()
		end)
		--end
	end
end

Nothing about it is local/client sided.

I will give changing the Network Ownership a go.

This is very strange, one thing that you’re doing that could be problematic is using an actual projectile that has to hit something. The position of moving things in the workspace will vary from client to server to other client. The target may think it was missed while the shooter sees a hit due to replication lag, etc.

What is puzzling here is, I don’t know how, if the server thinks it was a hit, that the object would continue undamaged. Maybe by the time the server explodes the rocket, the plane has moved on.

One thing I would recommend not doing is instancing the part into the workspace like you did here:

local ex = Instance.new("Explosion",workspace)

It would be better if you did:
local ex = Instance.new("Explosion")

The explosion object will explode as soon at its parented. So, the last thing you should do before you parent it to the workspace would be to set the position to the rocket, or better yet, set it to the position of the thing it hit if you can grab that object(perhaps hit.Position in your example). Then…

ex.Parent = workspace --this will trigger the explosion

This way even if the object had moved in space, you know it was hit so you can position the explosion to the target.

1 Like

Update: I am still having issues with it, even when I set network ownership. What else can I possibly do??

I have this code execute when a player enters the pilot seat:

for _,d in pairs(Vehicle:GetDescendants()) do
			if d:IsA('BasePart') or d:IsA('MeshPart') or d:IsA('Seat') then
				local canSet,errorReason = d:CanSetNetworkOwnership()
				if canSet then
					d:SetNetworkOwner(Player)
				else
					warn("Cannot change the Network Ownership of "..d:GetFullName().." because: "..errorReason)
				end
				--d:SetNetworkOwnershipAuto()
			end
		end

Vehicle is the plane.

That is not how it works… When the player sits in the driver/pilot seat, that is where you will set the model (a group containing all the body parts of the vehicle or aircraft) NetworkOwnership to player.

It should look something like this,

VehicleSeat.ChildAdded:Connect(function(Child)
	if Child.Part1.Name == "HumanoidRootPart" then -- To verify if the child is actually a player.
		local Player = Players:GetPlayerFromCharacter(Child.Part1.Parent) -- To get reference of a driver/pilot
		VehicleSeat:SetNetworkOwner(Player) -- To set the vehicle/aircraft NetworkOwnership to the driver/pilot
	end
end)

In this way, this will signal the server and client that you are transferring the NetworkOwnership aka granting Physical Ownership/Control of the whole vehicle/aircraft to the driver/pilot.


Even still, the issue persists.

Is it because I have :SetNetworkOwnershipAuto() being done when the pilot exits the seat? Or is it because the pilot seat isn’t a VehicleSeat?
Screen Shot 2021-05-05 at 1.47.13 PM

It even continues to happen when I set the NetworkOwnership of the server-sided plane control system:

Though, the seat it uses is a VehicleSeat, so after editing things a bit, the pilot’s client showed him or her getting shot down… but they would be invisible to everyone else.

For some reason, I feel like it something has to do with your shot down script. Could you explain a little more in details about how your shot down script work?

@SourceShahb
In the post I replied to, that is the shot down script. It basically runs a loop of all the players in the game, detects if a) their player is within range and b) if they are in an aircraft, where it targets them, and shoots rockets at them.

Rockets will explode when they hit something, obviously. I think the issue is when the rockets hit the character, where the character will be frozen in the sky.

Isn’t that the part of the shot down script? How exactly does the aircraft or the pilot (player) know that they’re being shot?

I think it’s the body movers that is still there after the aircraft is shot down, in which could be the reason why the player is floating or you could say frozen in mid air.