Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

PlayableDirector.Evaluate and duration generates GC

Discussion in 'Timeline' started by james7132, Feb 2, 2018.

  1. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    110
    I am currently using Timeline to control individual characters in a fighting game, and must manually control and evaluate multiple timelines per frame. Any given timeline may be stepped or evaluated multiple times per FixedUpdate, due to needing to support rollback netplay. It is working well, but it is generating a lot of garbage. Each call to PlayableDirector.duration and PlayableDirector.Evaluate both generate 80 bytes of garbage per Timeline. With up to 8 timelines in use and potentially 60 ticks to fast forward as a result of rollback netplay, that can generate 76.8kb of garbage in one (Fixed)Update. My question: is this garbage necessary? and if it isn't, can this be removed?

    Tangentially related: is it possible to run these evaluations as a part of the C# Jobs system?
     
  2. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,007
    There should not be any GC allocs coming from Evaluate(), unless the instance is getting rebuilt for some reason (I can't see why it would).

    What types of tracks is the timeline composed of? Any hints from the profiler about where the garbage is coming from?

    C# Job system in timeline -> not yet, but in progress. C# jobs and playables are a perfect fit together.
     
  3. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    110
    The timeline, for the most part, is only composed of two animation tracks that are targeting the same Animator.

    Here's what the profiler is showing on every update made. Also correction, it seems to be allocating 40 bytes per Director used.

    upload_2018-2-2_14-44-29.png

    Here's the code called to evaluate the state. Both the call to duration and Evaluate seem to be generating GC here.

    Code (CSharp):
    1.     if (timeline != Director.playableAsset) {
    2.       Director.Play(timeline);
    3.       stateDuration = Director.duration;
    4.     }
    5.     Director.time = state.StateTime % stateDuration;
    6.     Director.Evaluate();
     
  4. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,007
    Ah, thanks! Which version of Unity is this? I'll look into it.
     
  5. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    110
    It's the latest 2017.3 release. It should be noted that I do swap out the playable asset on occasion as a part of a state machine I built around the Director, and it is rebuilding the timeline playable at transition points, but this GC is happening at every update tick, not just the ones where the timeline is changed.
     
  6. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,007
    I haven't been able to reproduce this. Do you get the allocations if the timeline just plays without the script that forces an evaluation?
     
  7. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    110
    upload_2018-2-5_22-35-19.png

    If I disable the forced evaluation, it still allocs GC.
     
  8. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    110
    Here are the Inspector settings

    upload_2018-2-5_23-22-52.png
     
  9. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,007
    I'm able to reproduce it under the .NET 4.6 Scripting Runtime. Is that what you are using as well?

    We'll look into that and get a fix out ASAP.
     
    Peter77 likes this.
  10. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    110
    Yes, I am using the new runtime, I probably should have mentioned that from the get-go.
     
    Peter77 likes this.
  11. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    4,112
    It's often more efficient for UT if you attach a project to reproduce the issue. The easier it's for UT to reproduce an issue, the more likely it's that they're actually going to look at it.
     
  12. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    110
    As an alternative to this, I'm experimenting with try to create a single playable graph instead of swapping out timelines. I have a large number of timelines, on the order of 80-200 per object playing it. The end result is something similar to a code-based Animation Controller, except with the base elements based on Timelines instead of simple Motions. With only one or two of the timelines having non-zero weight, are there potential performance issues if I attempt to merge all of those timelines under a single playable graph?
     
  13. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,007
    I don't think there will be any difference in performance. We get asked frequently questions like 'how many timelines/playable graphs can be played at once' and the answer is it's less about the number of graphs and more about the number of outputs (i.e. tracks) in total. Each output has a subgraph that is traversed and processed.

    E.g. Having 25 animation tracks running is roughly equivalent to having 25 animation controller playing. The cost will be dependent on what is being animated.
     
  14. origamipandastudio

    origamipandastudio

    Joined:
    Apr 1, 2019
    Posts:
    1
    Was there a fix for this?
     
  15. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,007
    Possibly. There have been a few related fixes since that time. Are you still seeing allocations in PrepareFrame?