Open 4X3L82 opened 1 month ago
Based on this comment by @patwork on a similar issue, I was able to resolve this:
I've added %sub.restart()
just after the %main.restart()
for the button. Now when the button is pressed, the emitter does its thing and both main & sub emitter send the finished()
signal.
However, things still don't look/feel right to me. Basically, a double restart()
to make a single effect work seems gratuitous.
Without the restart()
on the sub-emitter, the whole particle effect (both main+sub) work fine. There's no (visual) feedback that the restart()
is missing/required on the sub-emitter and not just main. Shouldn't the restart()
on the main emitter trickle down and automatically fire off a restart()
on its own sub-emitter(s)?
Or rephrased: Is there ever a case where you want to restart()
the main emitter without restarting its sub-emitter(s)?
If all the above is fully expected behavior, including restart()
not trickle down to its own sub-emitter(s), then I think me (and probably others too) would benefit from clearer documentation.
This case is different from the one described in https://github.com/godotengine/godot/issues/93991. I don't want to speak for the authors of the GPU Particles code, but in my opinion in that (not this) case is an oversight of a possible situation where the one_shot
flag is set by the script when the particle emitter has been already added to the tree and passed its initialization.
💣 warning, below is just my current understanding, not confirmed by Godot devs
This case refers to something else, namely sub-emitters
. The difference is that you do not have a problem with the finished
signal in the main emitter, but in the sub-emitter that is triggered by it.
I was looking at the GPU Particles code for the first time yesterday so my conclusions are not necessarily 100% correct, but as far as I can see, sub-emitters do not send signals because they are never emitted on their own. In fact, the effect from a sub-emitter is "attached" to the renderer queue of the emitter that triggers it.
If you look in the scene's live-view debugger at the behavior of the emitters in your example, you'll see that the sub-emitter never changes its "Emitting" state, even when the results of its action start to appear on the screen. Therefore, if it is never emitted, it cannot return the finished
flag.
This also confirms why you only received the finished
signal when you manually started the sub-emitter using restart()
.
These are the words from the documentation:
When you set a particle system as the sub-emitter of another, the system stops emitting, even if the Emitting property was checked. Don't worry, it didn't break. This happens to every particle system as soon as it becomes a sub-emitter. You also won't be able to re-enable the property as long as the particle system is used as a sub-emitter.
Even though the parent particle system can be selected from the list of available particle systems, a particle system which is its own sub-emitter does not work in Godot. It will simply not spawn. The same is true for any other kind of recursive or self-referential sub-emitter setup.
https://docs.godotengine.org/pl/4.x/tutorials/3d/particles/subemitters.html
Tested versions
System information
Godot v4.3.beta2 - Manjaro Linux #1 SMP PREEMPT_DYNAMIC Mon May 27 03:41:25 UTC 2024 - X11 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3080 Laptop GPU - AMD Ryzen 9 5900HX with Radeon Graphics (16 Threads)
Issue description
I've created a simple GPUParticles2D effect with a main+subemitter, both set to OneShot and I want to know when the whole effect is done. I want to know when it's done so I can then destroy the effect (cleaning up). This could be done by using the
finished()
signal of the subemitter, however, it's never emitted.Goal: I need the
finished()
signal from the oneshot subemitter to know when the whole GPUParticles2D effect is done, so I can then callqueue_free()
to make it clean itself up.Steps to reproduce
print()
statement)Minimal reproduction project (MRP)
subemitter_no_finished.zip
This MRP has a button to
restart()
the main emitter, and 2 print statements connected to the 2 finished() signals of the main and sub emitter. Once the button is pressed, you can see the particles doing their thing. At the end of the main emitter, two things happen: "main done!" is printed, and the subemitter kicks in. Then at the end of the subemitter, nothing happens.I expected the finished() signal of the sub emitter to emit, which would then print "sub done!".