So I have recently read an article on the devforum that replicating particles to clients instead of particles to the whole server makes the load on the server way lower.
I was trying to make it through a player calls :FireServer() and then includes what particles and where to displace them, then the server loops through the players and calls :FireClient() on them and sends them those parameters. This is will be mainly used in my gun game.
However, on the last stage of the process, a parameter which is the particle one turns out to be nil. The server clones the particles from what the client sent and then sends it to the other clients waiting to replicate it.
Here's the code for when a player using a gun is about to replicate: FirePoint is just the tip of the gun while Settings.FireRate is the time elapsed to destroy it and the second parameter is just the visual effect.
local function ShootTool() -- Casts a ray and makes a beam if Values.Ammo < 1 then Sounds.NoAmmoClickSound:Play() Values.Shooting = false return end ParticleRemoteEvent:FireServer(FirePoint, SpotLight, Settings.FireRate) ParticleRemoteEvent:FireServer(FirePoint, ParticleEmitter, Settings.FireRate) Animations.ShootAnimation:Play() Values.Ammo = Values.Ammo - 1 Sounds.GunFireSound:Play() StopSprintTool() end
Here's the code for when the server receives those two calls and fires all the other clients to make this on their end:
-- // Services // -- local ReplicatedStorageService = game:GetService("ReplicatedStorage") local PlayersService = game:GetService("Players") -- // Remotes // -- local ParticleRemoteEvent = ReplicatedStorageService.Remotes:WaitForChild("Remote Events").ParticleRemoteEvent -- // Functions // -- local function ServerCall(Player, ParticleOwner, Particle, DestroyTime) for i,v in pairs(PlayersService:GetPlayers()) do local Clone = Particle:Clone() print(Particle.ClassName) print(Clone.ClassName) ParticleRemoteEvent:FireClient(v, ParticleOwner, Clone, DestroyTime) end end -- // Events // -- ParticleRemoteEvent.OnServerEvent:Connect(ServerCall)
Then here's the code for when every client receives the parameters and makes the visual effect on their end in the exact position/location:
-- // Services // -- local ReplicatedStorageService = game:GetService("ReplicatedStorage") local DebrisService = game:GetService("Debris") -- // Remotes // -- local ParticleRemoteEvent = ReplicatedStorageService.Remotes:WaitForChild("Remote Events").ParticleRemoteEvent -- // Functions // -- local function ClientCall(ParticleOwner, CloneParticle, DestroyTime) print(ParticleOwner.Name) print(CloneParticle) -- CloneParticle is nil for some reason CloneParticle.Parent = ParticleOwner CloneParticle.Enabled = true if DestroyTime ~= nil then DebrisService:AddItem(CloneParticle, DestroyTime) end end ParticleRemoteEvent.OnClientEvent:Connect(ClientCall)
I think the problem is just parameter mix up but I haven't seen a mix up so far, also I would use :FireAllClients() but that means I need to make a clone of the visual effect for every player so I use :FireClient() instead.