The problem: My projectiles, when fired, behave weirdly due to lag. This ranges from projectiles stuttering in mid-air, to having weird collision detection
The solution: Some clever use of the client and BasePart:SetNetworkOwner()
DISCLAIMER: This tutorial is for solving a common issue with physics-based projectiles, like ones from the classic ROBLOX Slingshot or Paintball Gun. For guns that use raycasting for hit detection, you may want to look into alternative solutions.
First, we need a functioning ranged weapon. This is simple, with some light math involved in its creation. We need to create a handleless Tool, then insert a Script, a LocalScript, and a RemoteFunction with the name "MouseLocation" inside of it. Then, a RemoteEvent should be placed in ReplicatedStorage.
local ReplicatedStorage = game:GetService("ReplicatedStorage") local POSITION_OFFSET = 8 local PROJECTILE_SPEED = 85 local SERVER_HITBOX_TRANSPARENCY = 1 local tool = script.Parent local player = tool.Parent.Parent local remote = tool.MouseLocation local event = ReplicatedStorage.RemoteEvent local head = player.Character.Head tool.Activated:Connect(function() local mouseposition = remote:InvokeClient(player) --gets the mouse from localscript local spawnpos = head.Position + ((mouseposition - head.Position).unit * POSITION_OFFSET) local velocity = (mouseposition - head.Position).unit * PROJECTILE_SPEED local projectile = Instance.new("Part") projectile.Size = Vector3.new(1, 1, 1) projectile.Shape = Enum.PartType.Ball projectile.Position = spawnpos projectile.Velocity = velocity projectile.Transparency = SERVER_HITBOX_TRANSPARENCY projectile.Parent = workspace projectile:SetNetworkOwner(nil) --this is the invisible server hitbox projectile projectile.Touched:Connect(function() --when server hitbox hits something, it destroys itself and explodes local explosion = Instance.new("Explosion") explosion.Position = projectile.Position explosion.Parent = workspace projectile:Destroy() end) event:FireAllClients(spawnpos, velocity, projectile) --tell the localscript to create a visual copy end)
local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local player = Players.LocalPlayer local mouse = player:GetMouse() local tool = script.Parent local remotefunc = tool:WaitForChild("MouseLocation") local event = ReplicatedStorage:WaitForChild("RemoteEvent") --client doesnt receive these objects instantly unlike server remotefunc.OnClientInvoke = function() return mouse.Hit.p --returns position of mouse to the server end event.OnClientEvent:Connect(function(spawnpos, velocity, projectile) local visualcopy = projectile:Clone() visualcopy.Position = spawnpos visualcopy.Velocity = velocity visualcopy.Transparency = 0 visualcopy.Parent = workspace --visual copy of server projectile projectile.AncestryChanged:Connect(function() visualcopy:Destroy() --when server projectile is destroyed, visual copy destroys itself also end) end)
If set up right, the tool should behave normally with no errors. Remember, the tool needs to be handleless!
Since we've created a visual copy of the projectile on every connected player's client, the projectile should look smooth for everyone. Furthermore, since we set the network owner of the server projectile to "nil", it means that the server has full network ownership over the server's projectile. That means that, instead of the projectile shifting between networks like with automatic network ownership, the projectile instead always sticks with the server's network.
If we didn't set the network ownership of the server projectile, the projectile would be heavily desynchronized, often looking like its exploding sooner than it should, changing the position of the explosion to somewhere far behind the impact point. If we didn't create the visual copies however, the projectile would look very jittery for everyone. Doing this allows you to have accurate physics-based projectiles, but also allow them to look good. For competitive games where precise aim is key, this information is invaluable for any ROBLOX developer.
I hope you've been able to glean something from this article, and hope you have a wonderful rest of your day.