Search Unity

Question Custom Spawn Over Distance

Discussion in 'Visual Effect Graph' started by Qriva, May 9, 2023.

  1. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,314
    I tried to create custom spawn over distance based on this thread.
    The problem is I fail to understand the trick with target position. To be precise I understand the concept and the problem with initial position, but I can't understand some random behaviours.

    There are projectiles spawned + pooled - all of them leave trail behind. The default spawn over distance block produces something like this:
    upload_2023-5-9_21-13-52.png
    Start position of trails is almoast always the same and segments correctly spawn during movement.

    I tried advanced example from the link (the last one) and it has no problems with initial particles, but start position is often randomly offseted:
    upload_2023-5-9_21-24-32.png

    Meanwhile I created my own simple version, but without targetPosition trick. For some reason it produces lines from world origin randomly (trail going up):
    upload_2023-5-9_21-28-38.png
    upload_2023-5-9_21-41-6.png

    I don't understand why this happens only to ~20% of projectiles. On top of this I tried to experiment and find the cause, by coloring particles to red when newLoop is true, but there was not even one red particle.

    I tried to remove initial event or created custom script that sends play event and sets position via event attributes, and this "fixed" the issue I think, but when I tried this (it runs just after projectile is spawned):
    Code (CSharp):
    1. eventAttribute.SetVector3("position", transform.position + Vector3.forward);
    Only some of them received offset, while I expected all of them to have it:
    upload_2023-5-9_21-53-37.png

    What am I missing?
     
  2. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,314
    Trail graph
    upload_2023-5-10_1-56-46.png
     
  3. PaulDemeulenaere

    PaulDemeulenaere

    Unity Technologies

    Joined:
    Sep 29, 2016
    Posts:
    154
    Hello,

    I have to admit I'm a bit confused and I'll probably need actual graph data to inspect what is happening.

    For reference and I think you already have this, the current implementation of SpawnOverDistance is here and the graph you shared is more or less equivalent with this implementation. I'm probably missing something.

    About this, I might have some idea where the confusion could come from. In your graph, when NewLoop is true, the current position is equals to old position leading zero computed distance and spawnCount always zero. You can try forcing the spawnCount to one and inspect the expected behavior.
    Also, to help the debug and check more deeply what is happening, you can use GetSpawnSystemInfo every frames logging the status for spawnCount, deltaTime, totalTime, oldPosition and newPosition.

    Additionally, there is a common misunderstood about this value: the NewLoop is only true during one frame, it can be used to reset some status but it won't be necessarily true for the first particle spawned. This is the difference between these two captures:
    _no_red.gif

    _with_red.gif
    On the second run, the Single Burst is forcing a particle to output during the really first frame.

    The position can overridden every frame in your custom spawn context, isn't it the condition about deltaTime which causes this issue ? It seems useless since you aren't computing any threshold (or rate) based on deltaTime.
    You can possibly try unchecking the Fixed Delta Time on your VisualEffectAsset.
     
  4. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,314
    Thank you very much for insight,
    Yeah, actually I suspected I skipped the first frame, when I forced spawn count to 1 on new loop there are red particles, however I think not all trails have it.

    I expected only the first segment (or part of trail) to be red and my logic was that when I spawn/activate object, it reinits vfx and everything is set to zero. The object is spawned in the target/final position (I don't spawn in zero and move), so when initial event runs I expect newLoop to be true, so old position should be the same as current one and even if there are no particles to spawn the value should be correct in next update.

    If I remove delta it condition I think it works, but in this case the whole thing becomes even more confusing - the original spawner has those checks (for treshold, but still there) and it works correctly, meanwhile recreating the same logic inside graph produces completely different results?

    I will try to create some simple example as the whole thing is integrated with projectile pooling system with simulation running on jobs. Maybe I will find out it is fault of my code, no clue.
     
  5. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,314
    Ok, I created demo. There are 3 spawn over distance and here are my observations:
    1. Original spawn over distance does not start exactly in the spawn place, but this is kind of expected and I think there are no huge differences. It works as expected and looks quite smooth, no errors.
    2. My "Custom" spawner looks similar to original one, but has the problem with the initial particle randomly (version with deltaTime).
    3. The advanced spawner (copied from your post) "Spawn Dist" has no origin problems, but it seems to "lag" in some way - the beggining and the end of trail has some kind of flickering behaviour, like it had lower framerate or spawned segments less often, also the start position is more random (offset) like I described in the first post.

    My current unity 2022.2.16
     

    Attached Files:

    PaulDemeulenaere likes this.
  6. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,314
    Just in case attaching gif with flickering:
    GIF 10.05.2023 16-40-43.gif
    If you decrease size of projectile sphere it will be easier to notice the difference.
     
  7. PaulDemeulenaere

    PaulDemeulenaere

    Unity Technologies

    Joined:
    Sep 29, 2016
    Posts:
    154
    Thanks for the repro, I didn't went through the three repro yet but let's start about the random position because I think I understand the root issue.

    First thing first, indeed, I'm reproducing your unexpected trail starting at zero:
    _reproducing.gif
    Am I looking at the right issue ?

    I confirm it's related to the frame with zero delta time, removing the fixed time step option is hiding the issue:
    _reproducing_fixed_delta_time.gif
    But it's only a workaround.

    The actual issue comes from this block:
    upload_2023-5-10_19-17-15.png

    If the previous frame after spawn was a zero deltaTime, then, you will store a Vector3.zero in old position here.
    Let me describe step by step what is happening.
    - With Fixed Time Step and default VFX Settings, the deltaTime can be 0, 16ms, 33ms or 50ms.
    => First frame after spawn, NewLoop is true, deltaTime is (randomly) equals to zero, at the end, we have:
    - OldPosition contains inputPosition
    - CurrentPosition contains (0,0,0) (nothing is writing it)
    - spawnCount = 0
    => Second frame deltaTime is 16ms
    - The really first block is copying CurrentPosition (0,0,0) to OldPosition
    - OldPosition contains (0,0,0) because assigned from CurrentPosition
    - CurrentPosition contains inputPosition
    - spawnCount = Rate * distance
    => It spawns your particle between (0,0,0) and InputPosition

    There are several way to fix this, but for your case, the most obvious way is probably initializing current and old position with the same value when NewLoop is true:


    However, while testing your subgraph and moving some blocks, I encounter another issue revealed by these steps:


    I would expect this wrong behavior to also affect the subgraph, the ticket UUM-35461 has been raised.
     
    Qriva likes this.
  8. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,314
    Oh my, yes this is the actual cause. The funny part is I already tried the same thing before, but I did put that block as first to execute, like this:
    upload_2023-5-11_13-6-8.png
    and all trails disappeared, and I tried it just now and the same thing happens :D
    I fail to see how this difference affects the graph logic - is it just me or it's a bug, perhaps even the same one?
     
  9. PaulDemeulenaere

    PaulDemeulenaere

    Unity Technologies

    Joined:
    Sep 29, 2016
    Posts:
    154
    Yes, it's a bug, it looks like the same issue, I initially found it trying to move the block relying on NewLoop at the beginning on the spawn context, it shouldn't have any impact on the outcome and it makes more sense but, it revealed there is something wrong with expression graph in this case.
     
    Qriva likes this.
  10. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,314
    Phew, so it looks like I am still sane, thank you very much for help :)
     
    PaulDemeulenaere likes this.