Projectile Replication delay

I am currently working on a weapon system and I am using the FastCast Module.
I’ve made the shooting client sided and I am also replicating it to all other clients.
The way I do it is the shooter fires, sends a remoteevent to the server, this sends a remotevent to all other clients and they create the projectile localy themselfs.

The thing is that there is some kind of delay in the projectile and it’s not in sync, like 1 sec away.
This has results like this

And it’s even worse when both players would move because the diffrence in sync would look bigger.
I know my players would hate this because they would ask themself how they are getting hit.
Does anyone have a fix for this? I tried making the bullet faster on the replicating client but that didn’t work to much.


It is unnecessary to create the bullet on each individual client, as there will be more delay because of bandwidth. What you can do is create the bullet on the server, and give the server network ownership of the bullet, so that there isn’t a “hopping” effect where it kinda stops - this occurs when the network owner of the bullet switches, usually switched to the client closest to the bullet, or the server if its too far away

Alternatively you can create the bullet on each individual client and you can compensate for the latency by shifting the bullet x studs forwards based on the latency of the call.

So if my bullet moves 100 studs per second and my remote call took 100 milliseconds that is 0.1 seconds you need to shift the bullet from on the client rendering it and so, position = base + rate * latency; in this case position = base + 100 * .1


but how would I actually do that? Like not show the projectile to the player who is shooting?
I would need to hide that bullet that he fired.
So his localbullet is only visible for him and all other clients see the server created bullet? Am I understanding that right?

I see, maybe this will work jeah.
Do you have a handy methode on how to get the latency of a client? Probably with tick() right?

You could have the client send the time they shot the bullet and then compare it to the time of the server. You can get the current “time” by using tick. So yes, use tick.

local latency = clientReceivedTime - myTime

1 Like

I’ll play around with it a bit and see if I can manage to get it working. Thanks for the answer :))
I’ll not mark it as answered yet, because I would like to get some more methodes :))
But I’ll mark it later on!

Sounds good! If you need any other clarification just ping me and I’ll respond if I can.

1 Like

Aight so I got the Latency diffrence now.
I get the shooting player time and send it via remotevent to server, server sends all clients a remotevent with the passed time from shooter and the client itself takes his own time value and - it with the shooter time, this way I get the milliseconds in between the shots. its 0.42 smth.

How would I actually use it to shift the bullet? Do I increase the bulletspeed or do you want me to actually spawn the bullet further in the direction?

This is my fire function

	local reptime = tick()
	local latency = reptime - currtime
	print("difference : "..latency)
	local RNG =
	local ImpactParticle = Tool.Handle:WaitForChild("ImpactParticle")
	local directionalCF =, direction)
	playerTool = Tool
	local direction = (directionalCF * CFrame.fromOrientation(0, 0, RNG:NextNumber(0, TAU)) * CFrame.fromOrientation(math.rad(RNG:NextNumber(MIN_BULLET_SPREAD_ANGLE, MAX_BULLET_SPREAD_ANGLE)), 0, 0)).LookVector

	local CosmeticBullet = game.ReplicatedFirst.Assets.Bullets:FindFirstChild(Tool.Name.."_Bullet")

	local FirePointObject = Tool.Handle:WaitForChild("GunFirePoint")

	local humanoidRootPart = Tool.Parent:WaitForChild("HumanoidRootPart", 1)
	local myMovementSpeed = humanoidRootPart.Velocity
	local modifiedBulletSpeed = (direction * BULLET_SPEED) + myMovementSpeed
	-- Prepare a new cosmetic bullet
	local bullet = CosmeticBullet:Clone()
	bullet.CFrame =, FirePointObject.WorldPosition + direction) *, 0, -CosmeticBullet.Size.Z/2)
	bullet.Parent = workspace.Bullets
	Caster:FireWithBlacklist(FirePointObject.WorldPosition, direction * BULLET_MAXDIST, modifiedBulletSpeed, ignorelist, bullet, false, BULLET_GRAVITY)
	-- Play the sound

cuz lets say I’ll modify the speed. I cannot actually * the speed with the latency because the speed would actually lower itself when I multiply it with something below 1.
100 * 0.5 = 50

1 Like

Just set the position of the bullet to be the barrel of the gun + how far it would’ve traveled under the circumstances of its speed and the latency.

And so, in relation to your code, I think it would be something like.

bullet.CFrame =, FirePointObject.WorldPosition + direction) *, 0, -CosmeticBullet.Size.Z/2 + (bulletSpeed * latency))

but lets say the latency value is 0.45 (which it is) then the speed would actually lower itself, which is not the effect we want.

Edit: just noticed we are not actually changing the speed, mb

Alright. After trying some stuff out and coming back to old methodes, I simply increased the bullet speed for the recieving clients by 2.
so the bullet is traveling twice as fast and it is working great, no matter the distance.

Using Tick() isnt the best idea because I believe tick is diffrent depending on Timezones.

Oh you are right. But you can mitigate the timezone problem by giving the client a “tick” when they join. Then just take the difference between the tick you sent and their tick and add that difference every time a call is made.

Glad to see you got your problem solved though!!

1 Like

Thanks for your help, you teached me some new stuff and I appreciate that :))

Wouldnt that be a problem since the bullet for the recieving clients will catch up and go further than the original bullet