Bullet Visualization Lag

I’m making a gun system, and even when I visualize the bullet on all clients, I’ve noticed there is some visible delay between when the player clicks and when the bullet gets visualized. This is even worse at higher ping, but for some reason I’ve seen some games that do not have this issue even at high ping?

Server Script

local function fireBullet(mousePosition: Vector3)
	local origin = muzzleAttachment.WorldPosition
	local direction = (mousePosition - origin).Unit * Constants.BULLET_LENGTH + 
		Vector3.new(random:NextInteger(-Constants.RAY_SPREAD, Constants.RAY_SPREAD),
			random:NextInteger(-Constants.RAY_SPREAD, Constants.RAY_SPREAD),
			random:NextInteger(-Constants.RAY_SPREAD, Constants.RAY_SPREAD))
	local raycastResult = Workspace:Raycast(origin, direction, raycastParams)
	local intersection = raycastResult and raycastResult.Position or origin + direction
	local distance = (origin - intersection).Magnitude
	replicateBulletRemote:FireAllClients(gun, intersection, distance) -- Visualize the bullet for all client
	if raycastResult then
		local part = raycastResult.Instance
		local humanoid = part.Parent:FindFirstChild("Humanoid") or part.Parent.Parent:FindFirstChild("Humanoid")
		if not humanoid then
			return
		end
		if humanoid.Parent:HasTag("Enemy") then
			humanoid:TakeDamage(Constants.BULLET_DAMAGE)
		end
	end
end

Bullet-Replicator Script

local function onReplicateBulletEvent(gun: Tool, intersection: Vector3, bulletLength: number, raycastPosition: Vector3?, raycastNormal: number?)
	if gun and gun:IsDescendantOf(game) then
		local handle = gun.Handle
		local muzzleAttachment = handle:FindFirstChild("Muzzle", true)

		if muzzleAttachment then
			muzzleAttachment.Smoke:Emit(5)
			muzzleAttachment.Flash:Emit(5)
		end

		local newBulletVisual = bulletVisual:Clone()
		newBulletVisual.Size = Vector3.new(0.1, 0.1, bulletLength)
		newBulletVisual.CFrame = CFrame.lookAt(muzzleAttachment.WorldPosition, intersection) *  CFrame.new(0, 0, -bulletLength/2)
		newBulletVisual.Parent = bulletVisualsContainer

		local bulletFadeTween = TweenService:Create(
			newBulletVisual,
			TweenInfo.new(.5, Enum.EasingStyle.Cubic, Enum.EasingDirection.Out),
			{Transparency = 1})

		local bulletSizeTween = TweenService:Create(
			newBulletVisual,
			TweenInfo.new(.5, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out),
			{Size = Vector3.new(0.025, 0.025, bulletLength)})
		local bulletColorTween = TweenService:Create(
			newBulletVisual,
			TweenInfo.new(.5, Enum.EasingStyle.Linear, Enum.EasingDirection.Out),
			{Color = Color3.fromRGB(100, 100, 100)})

		bulletFadeTween:Play()
		bulletSizeTween:Play()
		bulletColorTween:Play()

		task.delay(.5, function()
			newBulletVisual:Destroy()
		end)
	end
end

replicateBulletRemote.OnClientEvent:Connect(onReplicateBulletEvent)

what if you just made the server transfer the origin and mouse direction to all clients and let the clients do the calculation?

1 Like

what do you mean? so just let the client do all the maths for the intersection, distance, etc?

yea, and for the server, you mainly need to check if the origin is from the character and stuff. this is kind of exploitable though while writing this. maybe do calculations for server and client. while client is more visual and server does the damage.

1 Like

Are you suggesting me to use a system where the client does the raycasting and the server verifies it or am I just confused?

yeah the client does the raycasting and gives the visual.

1 Like

I tried doing a system like that but I just got confused, like, does that mean you have to handle the fire-rate, ammo, reloading etc, on the client? Like I want to make that kind of system but it confuses me so much how you would make it work

so basically what I thought is to minimize the delay between server and client. The animations will be done by client, basically make the client handle all the visual stuff in an instant by calculating in client instead of waiting for the server to calculate for them.

The server will instead check if the shot from the player hits the target, and then the server have verify checks like if the person is spamming reload too many times in a second, or is firing too fast. The server is just the verifier.

What I think I would do for the remote event is to send the character’s who has done the action, with what type of action they did, to all clients. the client will receive the character and the character actions. then find them on workspace and do the visuals.

Of course I can do only specifications as, I have no clue how to implement this myself lol. But I hope this gave an idea what to do. What I do think the server should only calculate for clients is the direction and send it to all clients. As that’s the only thing that uses math.random

1 Like

Bugs that could happen though: a different player may visually shoot at an object but still hit the player. Server delay is inevitable, just trying to minimize the delay as much as possible.

a client thats falling could shoot at a player but instead hit an object as they land on the server and then fire, again server delay.

1 Like

Thank you, can I message you if I have any issues?

Sure, I love giving thoughts onto how to solve a problem.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.