OnServerEvent is fired multiple times base on the number of players

  1. **What do you want to achieve?
    I want to make a bullet which is tweened and does hit detection on the client side. I use FireAllClients on a server script, and a local script receiving message from the server. In order to make the bullet work, I clone the bullet and parent it to the workspace; therefore every scripts inside the bullet should run and function.

  2. What is the issue?
    The tweening and hit detection work fine, but the issue is dealing damage to the hit player, for example, the bullet’s attack is 1 and it hits the player. The hit player should receive 1 damage, but if there are 3 players in the game, it will deal 3 damages.

  3. What solutions have you tried so far?
    I have looked up solutions on DevForum and found many threads about this, but none of them works in my case.

The bullet (which is named cressent_moon)
image

The server script

local atk = 1

hit.OnServerEvent:Connect(function(player, hit_char)
	
	-- Danage
	if hit_char then

		local hit_humroot = hit_char:FindFirstChild('HumanoidRootPart', true)
		local hit_hum = hit_char:FindFirstChild('Humanoid', true)

		deal_damage.take(hit_char, atk)

		if hit_humroot then

			-- Hit effect
			local newEff = hitEff:Clone()
			newEff.Position = hit_humroot.Position
			newEff.Parent = game.Workspace.hitboxes

		end

	end
	
end)

The client script

-- detecting collision
local done = false

runServ.RenderStepped:Connect(function()

	if done == false then

		local partsIn = game.Workspace:GetPartsInPart(hitbox, OverlapParams.new())
		if #partsIn > 0 then

			for i, v in pairs(partsIn) do

				if v.Name == 'HumanoidRootPart' then

					local hit_humroot = v
					local hit_char = hit_humroot.Parent
					local hit_hum = hit_char:FindFirstChild('Humanoid', true)

					if hit_hum and hit_char ~= who.Value then
						
						done = true
						track:Cancel() -- The tweening track
						hit:FireServer(hit_char)
						break

					end

				end

			end

		end

	end

end)

Thank you for reading. I have been struggle with this issue for days, so if anyone could help me with this, I would be very grateful.

1 Like

That’s because for every player in your game, the client script will be run. So for each player this line of code will happen:

It will tell the server to hit ‘hit_char’. And it will do this 3 times, because there are 3 players in the game.

You can fix this by either checking on the client if the hit_char is its own character.
By changing the if-statement in this block of code like so:

	local hit_humroot = v
	local hit_char = hit_humroot.Parent
	local hit_hum = hit_char:FindFirstChild('Humanoid', true)

	if hit_hum and hit_char ~= who.Value and hit_char == game.Players.LocalPlayer.Character then
						
		done = true
		track:Cancel() -- The tweening track
		hit:FireServer(hit_char)
		break

	end

Now this line of code will only be run once when a player has been hit. Because only the player itself is checking if they have been hit.

But I would suggest having the collision detection on the server and not on each client.
Let me know if you’re still having problems after reading this!

2 Likes

It worked! So basically, I just have to add a condition that makes the server script only run once. In my case, it’s by checking if the hit character is equal to the client’s character, who sends a message to the server. Thank you very much. Now I can proceed with my bullet system.

3 Likes

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