Search Unity

Question How to Start emitting particles when walking with player and stop when standing still?

Discussion in '2D' started by TaCqz, Sep 8, 2021.

  1. TaCqz

    TaCqz

    Joined:
    Jun 29, 2020
    Posts:
    11
    Hey guys,

    im fairly new to Unity and I guess it's a pretty easy task, but I was wondering how to start emitting particles from a particle system upon moving? I tried to use the Play() and Stop() functions, but as soon as I use the Stop() function anywhere in my code it just never starts playing.

    This is the Code im trying to use to control it. horizontalMove is my actual movement speed and GroundCheck() is pretty self-explanatory. Any Ideas?

    Code (CSharp):
    1.  if (horizontalMove > 0 && GroundCheck())
    2.         {
    3.             leftTrail.Play(true);
    4.         }
    5.         else
    6.         {
    7.             leftTrail.Stop(true, ParticleSystemStopBehavior.StopEmitting);
    8.         }
    9.  
    10.  
    11.         if (horizontalMove < 0 && GroundCheck())
    12.         {
    13.             rightTrail.Play(true);
    14.         }
    15.         else
    16.         {
    17.             rightTrail.Stop(true, ParticleSystemStopBehavior.StopEmitting);
    18.         }
    Cheers
     
  2. Unrighteouss

    Unrighteouss

    Joined:
    Apr 24, 2018
    Posts:
    599
    Hey,

    ParticleSystem.Stop() is a bit unintuitive in that it sort of "locks" the particle system and waits for all emitted particles to disappear before giving back control.

    Assuming everything else is correct, the ParticleSystem.Stop() is likely the issue.

    Instead, you can use ParticleSystem.emission to control when the particles are shown.

    Here is an example of how to use emission:

    Code (CSharp):
    1.     ParticleSystem particles;
    2.  
    3.     void Start()
    4.     {
    5.         particles = GetComponent<ParticleSystem>();
    6.     }
    7.  
    8.     void Update()
    9.     {
    10.         var emission = particles.emission;
    11.  
    12.         if (Input.GetKey(KeyCode.Space))
    13.         {
    14.             emission.enabled = true;
    15.         }
    16.         else
    17.         {
    18.             emission.enabled = false;
    19.         }
    20.     }
    21. }
    If anything is unclear, please let me know!
     
    richardkettlewell likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,752
    I do almost what @Unrighteouss does, except usually I vary the emission amount based on a quantity such as 'speed' or 'power', so that slow motion produces fewer particles than fast motion for instance.

    Here's the engine motor control for the particle system in Jetpack Kurt:

    https://github.com/kurtdekker/datas...Assets/Datasack/Particles/DSPSEmitOverTime.cs

    It's actually a totally generic Datasack -> ParticleSystem emit over time controller, but the relevant non-Datasack code would be:

    at Start():

    Code (csharp):
    1. ParticleSystem ps = GetComponent<ParticleSystem> ();
    2. em = ps.emission;   // em is class-private
    3. BaseEmitOverTimeRate = em.rateOverTime.constant;
    And then when value changes (or every frame if you're lazy, I doubt it matters):

    Code (csharp):
    1. // where percentage is the "input" on off value (0.0 to 1.0 nominally)
    2. em.rateOverTime = percentage * BaseEmitOverTimeRate;
     
  4. TaCqz

    TaCqz

    Joined:
    Jun 29, 2020
    Posts:
    11
    Sadly it still doesnt show the particles on my end. I figured it might be easier to spot any mistakes with the full code, so here it is (it's my playerController, still WIP, trying things out):


    Code (CSharp):
    1. public class PlayerController : MonoBehaviour
    2. {
    3.     [SerializeField] private float speed = 0f;
    4.     [SerializeField] private float jumpPower = 0f;
    5.  
    6.     // Particlesystem for trail when moving on ground
    7.     [SerializeField] private ParticleSystem leftTrail;
    8.     [SerializeField] private ParticleSystem rightTrail;
    9.  
    10.     public LayerMask groundLayer;
    11.     public BoxCollider2D bc;
    12.     public Rigidbody2D rb;
    13.     private float horizontalMove;
    14.  
    15.     // Update is called once per frame
    16.     void FixedUpdate()
    17.     {
    18.  
    19.         horizontalMove = Input.GetAxis("Horizontal");
    20.         rb.velocity = new Vector2(horizontalMove * speed, rb.velocity.y);
    21.  
    22.  
    23.         if (Input.GetAxis("Jump") > 0 && GroundCheck())
    24.         {
    25.             rb.velocity = new Vector2(rb.velocity.x, jumpPower);
    26.         }
    27.  
    28.         var leftEmission = leftTrail.emission;
    29.         var rightEmission = leftTrail.emission;
    30.         if (rb.velocity.x > 0 && GroundCheck())
    31.         {
    32.             leftEmission.enabled = true;
    33.         }
    34.         else
    35.         {
    36.             leftEmission.enabled = false;
    37.         }
    38.  
    39.  
    40.         if (rb.velocity.x < 0 && GroundCheck())
    41.         {
    42.             rightEmission.enabled = true;
    43.         }
    44.         else
    45.         {
    46.             rightEmission.enabled = false;
    47.         }
    48.  
    49.  
    50.  
    51.  
    52.     }
    53.     // Checks if the PlayerObject is on the Ground. To avoid jumping on walls it creates a BoxCast with an x slightly smaller than the total size of the BoxCollider
    54.     private bool GroundCheck()
    55.     {
    56.         float extra = 0.1f;
    57.  
    58.         // Creation of BoxCast
    59.         RaycastHit2D hit = Physics2D.BoxCast(bc.bounds.center, new Vector3(bc.bounds.size.x - 0.187f, bc.bounds.size.y, bc.bounds.size.z), 0f, Vector2.down, extra, groundLayer);
    60.         // Checks for collision here
    61.         if (hit.collider != null) return true;
    62.  
    63.         return false;
    64.     }
    65. }
    Thanks guys, Im pretty sure you can see that I am absolutely new to Unity :3

    Cheers
     
  5. Unrighteouss

    Unrighteouss

    Joined:
    Apr 24, 2018
    Posts:
    599
    Hey,

    I tested out your exact script, and the the left particles work (just in the wrong direction), so if they're not working for you there's likely something else that's wrong. The one thing that comes to mind that might be the issue is that your ground layer isn't set on your ground objects.

    The issue that's causing the right particle system to not work (and messing with the left) is on line 29:
    var rightEmission = leftTrail.emission;
    - I'll let you figure out what's wrong here :p

    This wasn't causing any problems for me, but you should also change your FixedUpdate() method to Update(). The former is meant for physics calculations, and setting velocity isn't a calculation, so you can do that in Update().

    One last thing is that on line 61 you have an "if" statement without any curly brackets. Apparently this works (which I actually didn't know), but it looks a bit confusing and it's recommend to always use curly brackets.

    If it's still not working, let me know, but after you make the above changes there won't be anything wrong with the script.
     
    Last edited: Sep 9, 2021
  6. TaCqz

    TaCqz

    Joined:
    Jun 29, 2020
    Posts:
    11
    Cheers man, I just figured it out. Dumb me disabled "Play on awake". Im just stupid.

    About the if-statement: I'll leave it as it is. I learned that it is slightly faster in compiling as it does not expect a "block" of instructions, but rather just one instruction as it is a one-liner.

    But cheers for the support guys, can be closed down :)
     
    Unrighteouss likes this.
  7. Unrighteouss

    Unrighteouss

    Joined:
    Apr 24, 2018
    Posts:
    599
    I've lost count of the number of dumb mistakes I've made that have cost me way too much time trying to fix haha. Glad you figured it out.