godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.11k stars 69 forks source link

Emit `finished()` in `GPUParticles`, without `one_shot` being true after `emitting` is set to false and the last particle is killed #9073

Open ettiSurreal opened 6 months ago

ettiSurreal commented 6 months ago

Describe the project you are working on

A Platformer with heavy use of particles.

Describe the problem or limitation you are having in your project

I use particles to do things like simple trails, but deleting the object it awkward in this case because it immediately removes the entire trail with it. So i simply disable the visibility of the sprite, set the particles emitting to false and await finished(), so it only frees when the particles stop emitting, except i never tested if the deletion actually works, and it turns out it doesn't and now i have dozens of memory leaks due to unexpected behavior.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The finished() signal on GPUParticles2D and GPUParticles3D should be emitted after emitting is set to false and the last particle is killed.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

The section above explains the behavior.

If this enhancement will not be used often, can it be worked around with a few lines of script?

Interestingly enough, there doesn't seem to be a way to work around this.

    gpu_particles.one_shot = true
    gpu_particles.emitting = false
    await gpu_particles.finished
    print("finished!")

    gpu_particles.emitting = false
    gpu_particles.one_shot = true
    await gpu_particles.finished
    print("finished!")

    gpu_particles.one_shot = true
    await gpu_particles.finished
    print("finished!")

None of these emit the signal, bug? So the only option is to do something like

    gpu_particles.emitting = false
    await get_tree().create_timer(gpu_particles.lifetime, false).timeout
    print("finished!")

It's a simple enough command to remember, like with me it might be something you may learn very late into a project, and it also makes it impossible to simply connect the finished() signal to queue_free().

Is there a reason why this should be core and not an add-on in the asset library?

Changes to a built in class.

Mickeon commented 6 months ago

This feels more like a minor oversight than something needing a proposal. Hopefully it can be addressed without much of an impact, because the workaround does definitely sound redundant.