Destroy smoke after it's gone?

Just wondering, is there a way to destroy the smoke particle from the Hierarchy after it disappears? I notice when playing the cloned smokes pile up and I’m worried this could slow down the game if there are too many. I don’t know if this is the case but it’s a concern.

The Destroy(gameObject); function will just destroy the brick, which has already been destroyed. How can we destroy the cloned smokes (or is this even necessary to do?)

1 Like

Hi @jholowka,

There’s a couple of ways you could achieve this, although I’ve not tested them.

You could attach a script to your Smoke prefab for the particle system. The script could check in the Update() method for the .IsAlive promperty of the particle system - if it isn’t destroy the game object.

The downside of this method would be that you are obviously having to check every frame in the Update() method, so it may not be as efficient.

An alternative would be to use a coroutine and set a time limit for destroying the particle system object, you could set this limit to be the Duration of the particle system, although a little testing may be required to ensure that the final particle disappears smoothly. I have read though that there may be some issues with timescale, e.g if you had any slow motion going on in your game, or a pause option for example, this may have an adverse effect on what you are trying to do.

My feeling is that using the first suggestion above would probably be the easiest to implement and as each particle is only in play for around a second the overhead using the Update() method shouldn’t be too bad, but it would most likely be proportional to the number of particle systems (bricks) you have on each scene.

All of the objects will be destroyed when the next scene loads unless you are specifying that they shouldn’t be (singletons for example DontDestroyOnLoad).

Hope this helps :slight_smile:

Good ideas here,

The good thing about Destroy(GameObject, time) is that you don’t even need to use a coroutine, the second parameter, that we usually don’t even use, is a timer, so if we put Destroy(gameObject,3f) it will destroy the gameobject after 3 seconds, I have been using this method a lot :sweat_smile:

He could use it on start as:

void Start()
{
Destroy(gameObject,3f);
}

Timescale is a pain to work with indeed =x I`ve used it in my game for some features and I had a hard time configuring all the time dependant features because of it.

1 Like

Here’s an example script to achieve the above, you can obviously rename it, potentially shorten it, but I have written it in a way that should be fairly straight forward to understand. I added the script via Add Component on the Smoke prefab and it does as desired, from the perspective of time scale / game pausing, I have only tested it via pausing the game running from the Unity editor but with success.

using UnityEngine;

public class ParticleController : MonoBehaviour
{
    private ParticleSystem _particleSystem = null;

    /// <summary>
    /// Initialisation
    /// </summary>
    private void Start()
    {
        Initialise();
    }

    /// <summary>
    /// Update
    /// </summary>
    private void Update()
    {
        Destroy();
    }

    /// <summary>
    /// Initialises the ParticleController
    /// </summary>
    private void Initialise()
    {
        _particleSystem = gameObject.GetComponent<ParticleSystem>();
    }

    /// <summary>
    /// Destroys the instance of the gameObject (Smoke Clone) if it is no longer alive
    /// </summary>
    private void Destroy()
    {
        if (_particleSystem.IsAlive(true) == false)
        {
            Destroy(gameObject);
        }
    }
}
2 Likes

But can’t he just use the Destroy(gameObject,time) under void Start() in a script inside the particle gameObject?
Once it get instantialized it will start the Destroy with the timer

Edit: oh… Now that I realized that the variable IsAlive is from the ParticleSystem class and that it will return false if the particle animation stops. Awesome code you have there Rob

1 Like

Hi Johnny, absolutely he can, whether he should is a different matter - and the same applies to the code example I have given above.

From what I read online today there could be issues around having it disposed of based on time due to the time scale / pausing etc… these are most likely not going to be issues for Block Breaker (unless anyone has added a Pause option :slight_smile: ) but I thought it worth mentioning.

Your solution will invariably work just as well and as long as the time value being passed through was at least as long as the duration of the ParticleSystem.

What would be quite cool, would be to put the third version together using the coroutine, and then profile all three against each other, using a scene that had a large quantity of block (a completely level) perhaps 50 or 100+ etc… that would give an indication as to which approach is more efficient but again, it would really need to all be under the same situation where time scale / pausing were either factors, or not.

:slight_smile:

1 Like

This test would be interesting to see indeed, I think that all the three options would work the same way even if we change the timescale, it should pause the animation and resume it after since everything is using the time as parameter, but as you said, it would need further testing

1 Like

…be my guest :stuck_out_tongue_winking_eye:

Although I think there would be some differences.

Not sure about the coroutine but I think the destroy method using a time limit would continue to run and destroy the particles whilst the game was paused.

Hi everyone, thanks for the replies and suggestions! As expected, you’re suggesting things that weren’t taught yet in the course.

My one original question that is still unanswered - is there any advantage or reason to actually do this? I feel like there is but I’d like to know from people who are more experienced at this than I am :).

I’ll be trying to implement this later.

2 Likes

There is, performance wise and sometimes there is a chance that if you don’t destroy an object that was not supposed to be there anymore, you could experience some strange behaviors and errors (not in this case since it is a simple game).

@Rob, just tried it:

void Start()
	{
		Destroy (gameObject, 3f);
	}

	void Pause()
	{
		if (isPaused == false) 
		{
			Time.timeScale = 0;
			isPaused = true;
		} 
		else 
		{
			Time.timeScale = 1;
			isPaused = false;
		}

	}

	void Update () 
	{
		// Pressing Space to start the test
		if (Input.GetKeyDown(KeyCode.Space))
		{
			Pause();
		}

	}

The pause function does stop the destroy timer, seems that anything that uses times as parameter stops counting if we set Time.timescale = 0, but I don’t know, I’ve seen just a few unity methods, perhaps there are some that gets the time value from elsewhere

Clearing up after yourself is deemed as good practice and not doing so can/will have potential costs on performance.

In this case, and remembering that this is fairly early on in the course, all of these items get destroyed when the next scene loads, so perhaps not really that big a deal - only a keen eye would spot that they aren’t - well done :wink:

You could argue that there could be a benefit in destroying them off immediately (as above), or, that adding code which is checked every frame to see if they should be killed off is more costly.

Either case could be true and as such, in this specific case, the only real way to be certain of the best approach for your game would be to start using the profiler to see whats going on behind the scenes.

Regardless of performance however I would offer that it is far better to always consider the tidying up after yourself approach, even if you add a // ToDo: comment reminding yourself to come back and see if it costs you anything by doing so. Not doing so is a little lazy and could lead to performance and other issues depending on the game/app/device/circumstance.

My experience with the housekeeping comes from system development. The number of times I have seen people create database connections and not tidy up after themselves which has had undesirable effects is countless.

As above, for this specific situation, you could start looking at profiling and seeing whats going on. Your tests with the different approaches would need to be the same/fair in order for a suitable comparison.

Update

Just went through and edited all my spelling mistakes, sorry, I was using my phone the first time round, whilst cooking my son’s dinner! :slight_smile:

1 Like

Hi Johnny, so that’s a good thing to know - what about if the timescale isn’t actually set to zero, and thus paused, but merely put into slow motion…

Consider a scenario where in a flashy version of Block Breaker, upon smashing a specific block, the camera zooms in an replays the destruction of the block which in turns creates a spectacular visual display of sorts - this is all done in slow-mo to add to the effect before whizzing back to normal game speed after the replay… anything peculiar happen then?

I note that there was a method previously on the ParticleSystem for destroying the object once it was finished, it has been removed in more recent versions, I wonder whether there is a scenario in which killing it off based on time was having an adverse effect, so it was removed - can’t think why else what appears to be useful functionality would be removed.

1 Like

Same behavior @Rob, I updated the Project with the testing I’ve done, it is the same project that I used to test the Efficienty on setting transform position, so you can experiment with both if you want.

There are two scripts, the DestroyCounter (which is the active) has two public variables, Destroytimer to set how many seconds before destroying the gameObject and Time Divider to set the number that will divide the timescale, when you enter in the play mode there will be a counter displaying how many seconds until the gameObject gets destroyed, and if you press space it will active the timescale modifier and will allow us to see in real time through the counter being displayed. It is working like a charm =)

code:

[code]using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class DestroyCounter : MonoBehaviour {

bool isPaused;
public float Destroytimer;
float Counter;
public float TimeDivider;
public Text NumberDisplayer;
void Start()
{
	Destroy (gameObject, Destroytimer);
	
}

void SlowEffect()
{
	if (isPaused == false) 
	{
		Time.timeScale /= TimeDivider;
		isPaused = true;
	} 
	else 
	{
		Time.timeScale *= TimeDivider;
		isPaused = false;
	}

}

void Update () 
{
	// Pressing Space to start the test
	if (Input.GetKeyDown(KeyCode.Space))
	{
		SlowEffect();
	}
	Counter = Destroytimer - Time.time;
	NumberDisplayer.text = Counter.ToString("0.00");

}

}[/code]

If you want to test the transform position efficiency, just activate the other script and deactivate the DestroyCounter, I used space to control both (recycling code :joy:) on the same gameObject (named as box).
let me know your thoughts

I don’t know, but I’m sure that there are situations that tweaking the timescale and making methods that are time dependant will cause some problems, but probably will cause problems to animations and etc too, regarding the replay feature, seems to be interesting, I don’t have a clue into how to do such a feature but I’ll surely look for it in the future!

Did you attach this script to the partical effects?

This was a test that I have done, I made another project just to test how timescale(pause and slowmotion effect) effects the destroy method, there is a copy of the project in the link I have posted above

I just tried this code, but it just disabled the smoke entirely…

you can disable it by adding a script to start with:

[code]
void Start()
{

Destroy(gameObject,time) // choose the time in seconds

}[/code]

ok after much tweaking I seem to have made it work, but my code ended up looking like this:

void Start () {
    DestroyObject(gameObject, 2f); // choose the time in seconds 
}
1 Like

is there an easier way than using two scripts?

Privacy & Terms