Hello, I am making a projectile shooting system where a projectile is shot from the player. It works perfectly fine on studio but when I go in-game it acts differently and is very jittery. Here is a video to showcase what’s happening:
I have really no idea why this is happening. I have the parts collisions turn off and even made the part massless but it still bugs out. I am using FastCast to achieve this here is my code:
Client
local Origin = HumanoidRootPart.Position + (HumanoidRootPart.CFrame.LookVector * 2)
local Direction = HumanoidRootPart.CFrame.LookVector
ReplicatedStorage.Events.Projectile:FireServer(Origin, Direction)
The roblox client uses a connection to a real server, meaning that projectiles can appear jittery or incorrect if they are modelled by the server, and was likely not appearing as the difference between the server and the client was much more minimal.
In order to circumvent ths, you can either use the Roblox physics engine which compensates for this (see BodyPosition) or do what some professional games do and have the server interpret the path of the projectile (for hit casting) and then the local client maps the projectile so it appears smooth.
You’d have to manually replicate it to each client. Whenever a projectile is shot, have the server fire a remote to each client which then all create and move / animate that clientside projectile. It not only appears a lot smoother but also saves on network bandwidth.
Note that you would need to handle things like hit detection on the server which might be a bit difficult.
Here’s a quick demonstration of what this might look like:
-- Server projectile handler
local ProjectileRemote = ReplicatedStorage.ProjectileRemote
local TryFireProjectile = ReplicatedStorage.TryFireProjectileRemote
local function CreateProjectile(position: Vector3, direction: Vector3)
ProjectileRemote:FireAllClients(position, direction)
end
TryFireProjectile.OnServerEvent:Connect(function(player: Player, ...)
-- etc etc
CreateProjectile(whatever, whatever)
end)
-- Client projectile handler
local RunService = game:GetService('RunService')
local ProjectileRemote = ReplicatedStorage.ProjectileRemote
local function CreateProjectile(position: Vector3)
-- etc
return projectile
end
local projectiles = {}
ProjectileRemote.OnClientEvent:Connect(function(position, direction)
local t = {
Direction = direction,
Instance = CreateProjectile(position)
}
table.insert(projectiles, t)
task.delay(4, function()
local ind = table.find(projectiles, t)
if ind ~= nil then
table.remove(projectiles, ind)
end
end)
end)
RunService.Heartbeat:Connect(function(delta: number)
for _, projectile in projectiles do
projectile.Instance.Position += projectile.Direction * delta -- Deltatime is important
end
end)