Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Spawn Over Distance is causing GC spikes

Discussion in 'Visual Effect Graph' started by FlightOfOne, May 4, 2021.

  1. FlightOfOne

    FlightOfOne

    Joined:
    Aug 1, 2014
    Posts:
    668
    I am getting continuous Garbage Collection spikes with the Spawn Over Distance node. Frame rate jumps down a lot when this happens. Any ideas on how to prevent this, am I doing something wrong to cause this? Thanks!




    upload_2021-5-4_7-5-38.png


    upload_2021-5-4_7-4-25.png
     
  2. SniperED007

    SniperED007

    Joined:
    Sep 29, 2013
    Posts:
    345
    FYI - this still hasn't been addressed in Unity 2022.1.16
     
  3. PaulDemeulenaere

    PaulDemeulenaere

    Unity Technologies

    Joined:
    Sep 29, 2016
    Posts:
    146
    Hello,
    Sorry for the late answer, we missed the initial message.
    The block SpawnOverDistance relies on VFXSpawnerCallbacks interface, within the VisualEffectGraph package, there are a few blocks implemented this way :
    - LoopAndDelay (which is now a behavior directly configurable on the spawn context)
    - SetSpawnTime
    - IncrementStripIndexOnStart
    - SpawnOverDistance

    For performance, when possible, we recommend avoiding usage of these spawn blocks for two reasons:
    - This unexpected garbage (which is actually an issue, you can track the resolution here)
    - These blocks are forcing the VisualEffect component update to be processed on the main thread (with current implementation of VFXSpawnerCallbacks)

    However, the behavior of spawn over distance can generally be emulated using graph:
    _SpawnOverDistance.gif

    We are aware this VFX looks like a convoluted workaround but, even if the unexpected garbage is solved, the resolution of the performance issue with SpawnOverDistance will probably internally produce the same kind of graph.
     

    Attached Files:

    Last edited: Sep 16, 2022
    SniperED007 likes this.
  4. SniperED007

    SniperED007

    Joined:
    Sep 29, 2013
    Posts:
    345
    Thanks for the quick response.
     
  5. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,293
    This is interesting use of spawn context! I had no idea I could even do that. Does spawn context runs every frame and checks it's spawnCount to emit particles and this is all it does?
     
  6. PaulDemeulenaere

    PaulDemeulenaere

    Unity Technologies

    Joined:
    Sep 29, 2016
    Posts:
    146
    Yes, the spawn context is run for every frame update and the spawnCount attribute is accumulated, when it reaches a value greater than 1, then the following context (generally an Initialize Context) receive a hit.

    There is one subtlety, the update is processed whatever the Loop State of the Spawn Context, the VFXSpawnerState.playing is actually equivalent with loopState == VFXSpawnerLoopState.Looping (this behavior was used in LoopAndDelay to stop or reenable playing)

    To illustrate this point, here an exemple of block Constant Rate emulated within the graph, it can help to understand how it works behind the curtain:
    _Emulate_Constant_Spawn_Rate.gif
     

    Attached Files:

    Qriva likes this.
  7. SniperED007

    SniperED007

    Joined:
    Sep 29, 2013
    Posts:
    345
    I have a problem with this, my VFX is Instantiated and that seems to cause the
    The above change however causes a few other issues:
    - spawning in a prefab with the VFX the on it causes an initial burst of all the particles at the spawn position.
    - doing this (pic below) no longer works as from what I can tell Get Attribute oldPosition (Source) now is always 0,0,0.
    upload_2022-9-17_9-52-40.png
     

    Attached Files:

  8. PaulDemeulenaere

    PaulDemeulenaere

    Unity Technologies

    Joined:
    Sep 29, 2016
    Posts:
    146
    The workaround I showed previously doesn't take the initial state into account. You can mimic the behavior of SpawnOverDistance testing the SpawnState.newLoop value, it will initialize old position with current position:
    SpawnOverDistance_With_Init_Smaller.gif

    This approach probably enough for most usage but it doesn't strictly emulate the behavior of SpawnOverDistance, I've quickly tried an equivalent graph of this implementation but it's probably partially wrong because it doesn't exactly fit the spawn rate of the custom callback (every red square are supposed to have a yellow triangle inside):
    _advanced_emulation.gif
    I don't expect such a complexity needed for the general purpose.

    About this, I'm not sure to understand the problem, it should be (0,0,0) only during the first frame, if you are using a really recent Unity version and enabled instancing, it could be related to this issue.

    All in all, the problem with unexpected garbage creating spikes in GC has been identified, you can follow this issue.
     

    Attached Files:

    Last edited: Sep 19, 2022
    SudoCat, SniperED007 and Qriva like this.
  9. SniperED007

    SniperED007

    Joined:
    Sep 29, 2013
    Posts:
    345
    thanks again, this has been the best support I've ever received from Unity.
     
    PaulDemeulenaere, Qriva and Julien-A like this.