- Home /
Particles disappear when game object is destroyed...
I apoogize in advance if this has been asked. I couldn't find it.
I have a game object that emits particles as it flies. It is basically a magic bolt type effect. The game object is destroyed when it hits an enemy, but unfortunately all of the remaining living particles are also destroyed simultaneously instead of flickering out as they should.
Is there an easy way to prevent this? Please keep in mind that I am a noob to Unity, and a poor coder in general.
Thanks in advance for any help.
Answer by syclamoth · Sep 18, 2011 at 09:56 AM
If you want to have the particle effect fade out nicely, put the particle effect on a child object of your magic missile and then have something to the effect of the following code on the missile itself:
public ParticleEmitter emit;
// blah blah rest of code
// Call this immediately before you destroy your missile
public void DetachParticles()
{
// This splits the particle off so it doesn't get deleted with the parent
emit.transform.parent = null;
// this stops the particle from creating more bits
emit.emission = 0;
// This finds the particleAnimator associated with the emitter and then
// sets it to automatically delete itself when it runs out of particles
emit.GetComponent<ParticleAnimator>().autoDestruct = true;
}
And then you're all set! Assign the particleEmitter object to your script in the inspector, and then when you want to delete your missile, call that bit of code and it will neatly separate the particle effect at the same time as ordering it to clean itself up when it's finished.
I had a little trouble because I think your code is in C#, and my script is in js, but I worked at it, and your answer helped me immensely. With great people here willing to help, I think I may actually be able to learn this given enough time.
Thank you so much :)
Sorry about the C# thing- I keep forgetting that most people here use JS! Can't stand it personally...
No problem at all. I have no strong preference for it except that the script reference (which often leaves me more confused than before I looked at it), and many of the tutorials are in js. As far as I can tell no language is particularly better than the other for this, and I often find myself wishing there was only one language being used.
I'm sure the coding gurus can jump back and forth with ease, but learning one new language is hard enough. Thanks again for the help.
Answer by djirving82 · Oct 29, 2018 at 10:22 AM
I used a little from the other answers here and this code works great for me. This code is for multiplayer setups, remove the "[Command]" and "Cmd" if you are not using NetworkBehaviour for multiplayer. Also make sure to change your Stop Action to "destroy" in your Particle System.
public ParticleSystem emit;
// blah blah rest of code
// Call this immediately before you destroy your missile
[Command]
void CmdDetachParticles()
{
// This splits the particle off so it doesn't get deleted with the parent
emit.transform.parent = null;
// this stops the particle from creating more bits
emit.Stop();
}
Answer by jsnetors · Sep 29, 2015 at 09:07 AM
For anyone having this problem in Unity5, this solution won't work as-is.
Unity 5 took away many legacy things, ParticleAnimator included.
The solution I found and what should work to most people using U5 is as follows:
This is a code that puts AutoDestroy back to the particle. You just create a new script, put this code inside and then put the code inside the particleSystem you want to terminate:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class AutoDestroy : MonoBehaviour
//This code destroys the particle's GameObject once it's Start Time is over.
//Also, if you're having issues with particles vanishing after you get far from them, just set their XYZ Scale values to 2, 2, 2
{
private float timeLeft;
public void Awake()
{
ParticleSystem system = GetComponent<ParticleSystem>();
timeLeft = system.startLifetime;
}
public void Update()
{
timeLeft -= Time.deltaTime;
if (timeLeft <= 0)
{
GameObject.Destroy(gameObject);
}
}
}
Now, to the projectile gameObjects script:
public ParticleSystem emit;
void OnTriggerEnter2D(Collider2D other) //Can be other ways of detecting
{
// This splits the particle off so it doesn't get deleted with the parent
emit.transform.parent = null;
// this stops the particle from creating more bits
emit.emissionRate = 0;
//This destroys the projectile
Destroy (gameObject);
}
Peace.
Answer by qiaosic · Nov 16, 2016 at 08:38 PM
Thanks for all the answers above, here is the one that work for me. Other solution for Unity 5 without using autoDestruct . Using ParticleSystem.IsAlive().
private void Update()
{
// check if the particle system still alive.
if (_detached
&& null != _curParticleSystem
&& !_curParticleSystem.IsAlive())
{
if (null != _parent)
{
//put it back to the parent.
transform.parent = _parent;
_detached = false;
}
else
{
// destroy it.
Destroy(this);
}
}
}
public void Detach()
{
_detached = true;
_parent = transform.parent;
// splits the particle off so it doesn't get deleted with the parent
transform.parent = null;
_curParticleSystem = GetComponent<ParticleSystem>();
if (null == _curParticleSystem)
{
return;
}
// stops the particle from creating more bits
_curParticleSystem.Stop();
}
Answer by killakiwi · Aug 04, 2017 at 07:31 AM
I wrote this after I couldn't find anything that I was happy with:
using UnityEngine;
using System.Collections.Generic;
public class ParticleDestroyer : MonoBehaviour {
static List<GameObject> ParticleSystemGameObjects = new List<GameObject>();
void Update () {
CheckAndDestroyDeadParticleSystems ();
}
static void CheckAndDestroyDeadParticleSystems(){
for (int i = 0; i < ParticleSystemGameObjects.Count; i++) {
bool AParticleSystemStillAlive = false;
ParticleSystem[] ParticleSystems = ParticleSystemGameObjects [i].GetComponents<ParticleSystem> ();
for (int j = 0; j < ParticleSystems.Length; j++){
if (ParticleSystems[j].IsAlive ())
AParticleSystemStillAlive = true;
}
if (!AParticleSystemStillAlive) {
GameObject.Destroy (ParticleSystemGameObjects [i]);
ParticleSystemGameObjects.Remove (ParticleSystemGameObjects [i]);
}
}
}
public static void Destroy(GameObject ParticleSystemToDestroy){
ParticleSystemGameObjects.Add (ParticleSystemToDestroy);
ParticleSystemToDestroy.transform.parent = null;
foreach(ParticleSystem ParticleSystem in ParticleSystemToDestroy.GetComponents<ParticleSystem>()){
ParticleSystem.emissionRate = 0;
ParticleSystem.Stop ();
}
}
}
You call it like this:
public void SwordSlash_Finished () {
ParticleDestroyer.Destroy(Particle);
Destroy(gameObject);
}
So the ParticleDestroyer is a class which uses static methods, the class itself is not static because I want to use the Update function, which can only be used off of classes that are derived from MonoBehaviour. This means you need to attack the script to a GameObject in your scene.
The Destroy function halts the particle systems activities and the CheckAndDestroyDeadPArticleSystems function constantly scans all particle systems and if there are no dead alive particles left it can safely destroy the GameObject. It also accounts for GameObjects with multiple ParticleSystems attached to them.
Your welcome.
Your answer
Follow this Question
Related Questions
using Contains(gameObject) to find and destroy a gameObject from a list 2 Answers
Particle System lifetime not affecting particles 0 Answers
How to destroy / hide a single particle? 2 Answers
Trouble with destroying a particle. 1 Answer
Trying to make a dust particle when the the player moves 1 Answer