Particles Disappear too Early

Not sure if this is the right topic to put this under, but I have a grenade that when it explodes, it spawns a custom particle to replace the default explosion effect. This is achieved thru activating the particle in a part in the handle of a clone, then shortly after disabling it.

For some reason, the particle randomly disappears, even though it does not do this if i preview the particles in studio. It only occurs when it is enabled then disabled through a script.

The bit of code that handles the particles after detonation:

				bomb.Parent.Handle.SmallExplosionParticle.ParticleEmitter1.Enabled = true
				bomb.Parent.Handle.SmallExplosionParticle.ParticleEmitter2.Enabled = true
				bomb.Parent.Handle.SmallExplosionParticle.ParticleEmitter3.Enabled = true
				bomb.Parent.Handle.SmallExplosionParticle.PointLight.Enabled = true
				bomb.Parent.Handle.fuse.Playing = false
				wait(0.3)
				bomb.Parent.Handle.SmallExplosionParticle.ParticleEmitter1.Enabled = false
				bomb.Parent.Handle.SmallExplosionParticle.ParticleEmitter2.Enabled = false
				bomb.Parent.Handle.SmallExplosionParticle.ParticleEmitter3.Enabled = false
				bomb.Parent.Handle.SmallExplosionParticle.PointLight.Enabled = false
				wait(8)
				bomb:Destroy()

How the particle should behave:

How the particle behaves when being activated thru a script (you can see it suddenly pops out of existance):

Any help or explanation as to why this is happening would be much appreciated!

1 Like

I don’t see a difference.

Characters : /

The particles in studio smoothly fade out, whilst the particles in-game look as if they suddenly disappear.

I would assume this is because of the bomb having been destroyed after the eight seconds. I would add some time before destroying the bomb for in-game. if that doesn’t work I’m not sure what the problem is.

2 Likes

That depends on the graphs of the studio. If you have in File>StudioSettings>Rendering>EditorQualityLevel level 3, the studio will run smoothly but you have lag when playing the game.

I don’t believe you fully understand what I am asking. Performance is no issue, the particle disappearing too quickly is the issue. Changing graphics settings does not effect the fact that they disappear early.

1 Like

Even if I more than double the time before the bomb is destroyed, it still has the same behavior.

I would post a bit more script that happens before and after this section… is the bomb a clone? Are you destroying the clone?

I can see the bomb disappears, so are you turning off collisions for the bomb so it disappears? If so, the bomb will automatically delete after falling a certain distance.

Could you include more code and maybe any errors that happen in the output?

local tool = script.Parent
local handle = tool.Handle
local debounce = false
local fuseTime = 2
local bvDelete = 0.2
local holding = false

local mousePos
tool.MouseRE.OnServerEvent:Connect(function(plr, mouseHit)
	mousePos = mouseHit
end)

tool.Activated:Connect(function()
	if not debounce then
		debounce = true
		wait(2.6)
		if holding == true then
			local bomb = tool.Handle:Clone()
			bomb.Parent = workspace
			bomb.Position = handle.Position
			bomb.CanCollide = true
			bomb.Parent.Handle.fuse.Playing = true
			bomb.Parent.Handle.fire.ParticleEmitter.Enabled = true
			bomb.Parent.Handle.fuse.TimePosition = 2.5
			local bv = Instance.new("BodyVelocity")
			bv.Velocity = mousePos.LookVector * 60
			bv.Parent = bomb
			tool:Destroy()
			delay(bvDelete,function()
				bv:Destroy()
			end)
			delay(fuseTime,function()
				local explosion = Instance.new("Explosion",workspace)
				explosion.Position = bomb.Position
				explosion.BlastRadius = 16
				explosion.BlastPressure = 12500
				explosion.Visible = false
				bomb.explode.Playing = true
				bomb.explode:Play()
				bomb.Parent.Handle.Transparency = 1
				bomb.Parent.Handle.SmallExplosionParticle.ParticleEmitter1.Enabled = true
				bomb.Parent.Handle.SmallExplosionParticle.ParticleEmitter2.Enabled = true
				bomb.Parent.Handle.SmallExplosionParticle.ParticleEmitter3.Enabled = true
				bomb.Parent.Handle.SmallExplosionParticle.PointLight.Enabled = true
				bomb.Parent.Handle.fuse.Playing = false
				wait(0.3)
				bomb.Parent.Handle.SmallExplosionParticle.ParticleEmitter1.Enabled = false
				bomb.Parent.Handle.SmallExplosionParticle.ParticleEmitter2.Enabled = false
				bomb.Parent.Handle.SmallExplosionParticle.ParticleEmitter3.Enabled = false
				bomb.Parent.Handle.SmallExplosionParticle.PointLight.Enabled = false
				wait(8)
				bomb:Destroy()
			end)
		end
	end
end)

script.Parent.Equipped:connect(function()
	holding = true
end)

script.Parent.Unequipped:connect(function()
	holding  = false
end)

No, only the transparency changes. There are no output errors.

I think the bomb falls through the floor when the physics owner switches to server. Do you know if the bomb is CanCollide on the server? If not either manually set the network owner to the person that threw the bomb when it’s thrown or set CanCollide to true on the server.

Yes, the script shown that changes the cancollide property is serverside. The localscript that I didn’t show shouldn’t be a problem because all it does is simply get the mouse position and play animations.

Just to clear something up, whats Bomb.Parent.Handle? Is that referencing itself there or is it a different part?

Yeah, it’s referencing itself. I made it that way because it was structured differently in a previous iteration of the bomb, and I never bothered to fix it as it practically does the same thing.

The Roblox engine’s discrepancy between server-client vision causes your issue. What the server sees is not always the same as what each player sees, and vice-versa.

Assuming you’re using a server script to control the particles, your wait() is based on server time (not client time). This is why the particles disappear prior to the completion of animation on the client.

You have two options:

  1. Move the particle effects to the client (preferred and efficient).
  2. Set up an event on the server, instead of using the wait() function.

Since option one is more performant in my opinion I’ll only cover that. However, if you find that option one does not meet your needs, I will gladly elaborate on setting up server-only events for particles.

Client-Based Particles:
Creating particles on the client is a very similar process to how one would create particles on the server. The fundamental difference is the use of Remote Events used to communicate information about particles from one client to every other client by using the server as a messenger.

In simple terms, we are going to trigger a remote event from the person throwing the bomb using:

--// CLIENT // --
local REP = game:GetService("ReplicatedStorage")
local event = REP:WaitForChild("RemoteEvent")

--// Run This Function On Explode //--
local function RelayExplosion(bomb)
    RemoteEvent:FireServer(bomb)
end

After that, we will receive the data on the server using:

--// SERVER //--
local REP = game:GetService("ReplicatedStorage")
local BombEvent = REP:WaitForChild("RemoteEvent")

BombEvent.OnServerEvent:Connect(function(plr, bomb)
    BombEvent:FireAllClients(bomb) -- This sends info about the bomb to every client
end)

Notice that inside of the function we have :FireAllClients(), this is what we use to relay the data.

Now, let’s go back to the client!

--// CLIENT AGAIN //--
local REP = game:GetService("ReplicatedStorage")
local BombEvent = REP:WaitForChild("BombEvent")

local function RelayExplosive(bomb)
    BombEvent:FireServer(bomb)
end
RelayExplosive(bomb)

--// ALL Clients will receive this! //--
BombEvent.OnClientEvent:Connect(function(bomb)
    local handle = bomb.Parent.Handle
    -- Enable all your emitters here
    wait(0.3)
    -- Disable your emitters here
    wait(8)
    bomb:Destroy()
end)

Destroying the Server Bomb:
The only issue now is deciding when to remove the server bomb you created when it was thrown.

You could move that system over to a server relay as shown above, but that could cause issues with hit detection if you’re unsure where the bomb landed.

The simple way out would be to hand network ownership over to the player that threw the bomb. This would mean any actions done on that specific client would replicate across all clients.

--// SERVER //--
local REP = game:GetService("ReplicatedStorage")
local BombEvent = REP:WaitForChild("RemoteEvent")

BombEvent.OnServerEvent:Connect(function(plr, bomb)
    bomb:SetNetworkOwner(plr) -- Sets network owner to thrower
    BombEvent:FireAllClients(bomb) -- This sends info about the bomb to every client
end)

However, if you would like to delve deeper, you could count clients. To do this, we need to fire an event from each client after they’ve finished deleting the bomb and wait for each client to do so.

We just need to make a few changes to the scripts to apply this method:

--// CLIENT AGAIN x2 //--
local REP = game:GetService("ReplicatedStorage")
local BombEvent = REP:WaitForChild("BombEvent")

local function RelayExplosive(bomb)
    BombEvent:FireServer(bomb, false) -- add false to not tally
end
RelayExplosive(bomb)

--// ALL Clients will receive this! //--
BombEvent.OnClientEvent:Connect(function(bomb)
    local handle = bomb.Parent.Handle
    -- Enable all your emitters here
    wait(0.3)
    -- Disable your emitters here
    wait(8)
    bomb:Destroy()
    BombEvent:FireServer(bomb, true) -- this event counts towards a tally
end)
--// SERVER //--
local REP = game:GetService("ReplicatedStorage")
local BombEvent = REP:WaitForChild("RemoteEvent")

BombEvent.OnServerEvent:Connect(function(plr, bomb, tally)
    if bomb and not tally then
        bomb:SetAttribute("Witnesses", #game:GetService("Players"):GetPlayers()) -- Get # of clients
        bomb:SetAttribute("Tally", 0) -- Set up tally for later
        bomb:SetNetworkOwner(plr) -- Sets network owner to thrower
        BombEvent:FireAllClients(bomb) -- This sends info about the bomb to every client
    elseif bomb and tally then
        bomb:SetAttribute("Tally", bomb:GetAttribute("Tally") + 1) -- Track # of clients finished
        if bomb:GetAttribute("Tally") >= bomb:GetAttribute("Witnesses") then -- if maxClients == finishedClients:
            bomb:Destroy()
        end
    end
end)

I hope this somewhat long-winded reply helps! :slight_smile:

3 Likes

I can see issues popping up with this when you have multiple bombs at the same time, but it’s probably not causing the issue right now.

Sorry for taking so much of your time, but can you check the explorer and watch the bomb instance during the explosion to see if the particles get deleted or if the bomb gets removed at the same time as the tool or something?

I think I have found the problem. I’m pretty sure the default roblox explosion works by destroying welds, so when the explosion goes off welds are broken and like you mentioned, certain parts may fall through the map. To counter this, the script will now anchor both the handle and explosion part.

Thanks for the help, and @Xitral sorry that you put effort into your post and it was not the solution, but I am really glad you would be willing to help me so much! I’ll be sure to use your reply as a resource if I experience an issue that would require a system like this.

p.s. I’m pretty new to the DevForum and idk what reply I should mark as the solution, so I’ll put it as your original reply saying that it could be falling through the map.

3 Likes