Search Unity

Question Perform action when VFX ends

Discussion in 'Visual Effect Graph' started by FlyingSquirrels, Feb 16, 2023.

  1. FlyingSquirrels

    FlyingSquirrels

    Joined:
    Sep 18, 2015
    Posts:
    84
    Is there a way (other than using the timeline feature ) to know when a VFX has finished?

    Thanks.
     
  2. JulienF_Unity

    JulienF_Unity

    Unity Technologies

    Joined:
    Dec 17, 2015
    Posts:
    326
    Hi! You can use VisualEffect.HasAnySystemAwake to know if all systems within your VFX component are sleeping. If you need the info at the system's granularity you can check VisualEffect.GetParticleSystemInfo and check the sleeping field.

    Note that the sleep state won't work correctly with some experimental features at the moment (strips and GPU events)
     
    Nit_Ram and FlyingSquirrels like this.
  3. merpheus

    merpheus

    Joined:
    Mar 5, 2013
    Posts:
    202
    Is there a way or a plan to allow CPU events on update blocks/gpu events? Having trouble to get info when particles flow from one point to the next and duration is unknown. I understand that there might be a sync problem within particles, but being able to get a signal is still useful for gameplay code.
     
    harpiagamesstudio and Qriva like this.
  4. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    104
    This can be a bit tricky for some and I can see that this question has been asked many times, many places (1 2 3):

    The problem with using VisualEffect.HasAnySystemAwake and something like VisualEffect.aliveParticleCount is that sometimes your control code is running when it gets spawned and therefore these calls can return true immediately and defeat the purpose. so pay attention to that and use a boolean intervention to stop that. In my case I have a script on my visual Effects graphs that return them to a pool when they are done emitting. So The Script is running as soon as the VFX is either, instantiated the first time or just re-positioned the next time it is called from the pool. Here is the Solution I came up with to illustrates it.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.VFX;
    3.  
    4. /// <summary>
    5. /// Manages the lifecycle of a GameObject with an attached VisualEffect component,
    6. /// returning it to an object pool when the effect is no longer active.
    7. /// </summary>
    8. public class ReturnVFXToPool : MonoBehaviour
    9. {
    10.     // Reference to the VisualEffect component on this GameObject.
    11.     private VisualEffect visualEffect;
    12.  
    13.     // Flag to track whether the visual effect has been played.
    14.     private bool hasPlayed;
    15.  
    16.     /// <summary>
    17.     /// Initialize the script by obtaining the VisualEffect component.
    18.     /// </summary>
    19.     void Awake()
    20.     {
    21.         // Get the attached VisualEffect component.
    22.         visualEffect = GetComponent<VisualEffect>();
    23.     }
    24.  
    25.     /// <summary>
    26.     /// Check each frame to see if the visual effect has stopped playing, and if so, return it to the pool.
    27.     /// </summary>
    28.     void Update()
    29.     {
    30.         // Check if there are no alive particles and the effect has previously played.
    31.         if (visualEffect.aliveParticleCount == 0 && hasPlayed)
    32.         {
    33.             // Return the GameObject to the object pool.
    34.             ReturnToPool();
    35.  
    36.             // Reset the hasPlayed flag to prepare for the next time the effect is played.
    37.             hasPlayed = false;
    38.             return;
    39.         }
    40.        
    41.         // If there are alive particles, mark the effect as having been played.
    42.         if (visualEffect.aliveParticleCount > 0)
    43.         {
    44.             hasPlayed = true;
    45.         }
    46.     }
    47.  
    48.     /// <summary>
    49.     /// Deactivates the GameObject and triggers the return to object pool process.
    50.     /// </summary>
    51.     public void ReturnToPool()
    52.     {
    53.         // Call to the ObjectPoolManager to handle the actual return-to-pool logic.
    54.         ObjectPoolManager.ReturnObjectToPool(gameObject);
    55.     }
    56. }