Inconsistent behavior on whether particle effects play or not.

I’m working on “Challenge 4” Challenge 4 - Soccer Scripting - Unity Learn and struggling with the particle effects playing or not. It seems many other tutorial users are having the same problem and I haven’t found any evidence of what can be causing this.

I am holding the space key down. The relevant code is being triggered (shown by the debug log in screen below). Note that in Figure 1 isplaying is true but that the “particles” mini window shows that it’s not playing. The thing is that if I mess around with the space long enough, it eventually does play and then seems to play on demand. See figure 2. It’s just that only sometimes holding down space doesn’t do anything. And then it just randomly works. Or sometimes I start a new game and it works fine with no issue. My code is below the screenshots below.

Best hypothesis - there is something weird going on with processing user input because whenever I tried to use my mouse to pause the play so that I could take a screenshot for this forum post the particle effect magically began playing. I had to use the hotkey “CTRL-SHIFT-P” so that I could take screenshots to show you. It’s seemingly random because sometimes it works just fine on the first play attempt.

Figure 1 : Effect not playing even though isPlaying is true.

Figure 2: It plays moments later in the same session with no code changes or restart.

void Update()
    {
        // Add force to player in direction of the focal point (and camera)
        float verticalInput = Input.GetAxis("Vertical");
        bool turbo = Input.GetKey(KeyCode.Space);
        int turboMultiplier;
        if (turbo) {
            turboMultiplier = 2;
            turboParticleEffect.Play();
            Debug.Log("Turbo Particle Effect Status:  "+turboParticleEffect.isPlaying);
        } else {
            turboMultiplier = 1;           
        }
        if (Input.GetKeyUp(KeyCode.Space)) {
            turboParticleEffect.Stop();
            Debug.Log("Turbo Particle Effect Status:  " + turboParticleEffect.isPlaying);
        }

        playerRb.AddForce(focalPoint.transform.forward * verticalInput * speed * Time.deltaTime * turboMultiplier);

        // Set powerup indicator position to beneath player
        powerupIndicator.transform.position = transform.position + new Vector3(0, -0.6f, 0);
        turboParticleEffect.transform.position = transform.position + new Vector3(0, -0.6f, 0);

    }

Interestingly ChatGPT had a great suggestion for me that seems to fix the problem above (I don’t know why and would love to understand)… but gives me a different problem.

The different problem is that once Stop() is called isPlaying continues to be true until the effect fully dissipates. That means future presses of the Space key have no effect for some cooldown period. But how would I get it to force Play() again in that case (without causing the issue from my original post).

Log of chat GPT below

Me: write me unity code to start and stop a particle effect based on holding down space key

ChatGPT: Sure, here’s an example code snippet in C# for Unity that starts and stops a particle effect when the space key is held down:

using UnityEngine;

public class ParticleController : MonoBehaviour
{
   public ParticleSystem particleSystem;

   void Update()
   {
       if (Input.GetKey(KeyCode.Space))
       {
           if (!particleSystem.isPlaying)
           {
               particleSystem.Play();
           }
       }
       else
       {
           if (particleSystem.isPlaying)
           {
               particleSystem.Stop();
           }
       }
   }
}

In this code, we define a ParticleSystem variable called particleSystem that represents the particle effect we want to control. Then, in the Update method, we check if the space key is being held down using Input.GetKey(KeyCode.Space).

If it is, we check if the particle effect is not already playing using !particleSystem.isPlaying. If it’s not, we start the particle effect by calling the Play() method on the particleSystem variable.

If the space key is not being held down, we check if the particle effect is already playing using particleSystem.isPlaying. If it is, we stop the particle effect by calling the Stop() method on the particleSystem variable.

Note that this code assumes that the ParticleSystem component is attached to the same GameObject as the ParticleController script. If it’s attached to a different GameObject, you’ll need to update the code to reference it correctly.

I never ever ever start / stop particle systems. That way lies glitches and madness.

Instead…

ParticleSystems (particlesystems): emitting in various positions in space (no play / stop):

1 Like

Thanks Kurt. I also found this thread just now that seems to provide more evidence of the buggy behavior of Play/Stop and other folks suggesting to use Emit.

Interestingly the suggested code in that thread also matches what ChatGPT suggested as a solution. It makes the behavior deterministic (which is great!) but now I’d trying to get a different behavior. This is what happens currently

  • When Play() is called, the effect works as expected
  • Space is let go and new particles are no longer emitted but the existing particle effect keeps playing. isPlaying returns true.
  • Play() does nothing until the previously emitted particles complete their effect. isPlaying stays true until completion of effect.
  • After waiting, triggering Play() now has desired effect.

Here’s what I’d like to have happen.

  • When Play() is called and the effect works as expected
  • Space is let go and new particles are no longer emitted but the existing particle effect keeps playing. isPlaying returns true.
  • Pressing space immediately after triggers Play() which emits more particles. In parallel, the previously emitted particles continue to animate.

Does this require two (or more) ParticleSystem objects to allow for multiple effects to happen in parallel. I’m a little apprehensive about coding with Emit() and specifying particle counts.

Not sure I follow your questions above. You never call Play() with my technique. Read again carefully how it gets set to play.

Again, I just don’t follow you. What part (as in, show me in the API documentation) is making you apprehensive?

Reading this Unity - Scripting API: ParticleSystem.Emit gave me the impression a lot of trial and error is involved with using Emit() to re-create what Play() does.

I understand that to create the effects I want, Emit() is probably necessary and appreciate you pointing me in that direction.

I have it working “good enough” for now with Play() and will relook at Emit() when I want to do some more advanced effects.

It seems like this is still the case.

But I can’t get Emit to work with the BakeMesh function.

I get the following assertion failure when calling BakeMesh.

Assertion failed on expression: ‘ps->array_size()’

That smells like an actual engine error.

Try all the usual strip-it-down and build-it-back-up approaches.

If you can get a tiny project to repro that bug, by all means file a bug (Help → Report A Bug)