Search Unity

Prevent Animator from auto updating?

Discussion in 'Animation' started by From-Soy-Sauce, Jul 20, 2016.

  1. From-Soy-Sauce

    From-Soy-Sauce

    Joined:
    Jan 7, 2014
    Posts:
    162
    Hello, I have been looking around all day to see if I could find a way to manually update the animator by a controlled amount of time by script, but I've failed to find anything to that effect.

    I have tried to do this, but it both prints read "GameTime"...

    anim=GetComponent<Animator>();
    print(anim.GetTimeUpdateMode());
    anim.SetTimeUpdateMode(UnityEngine.Experimental.Director.DirectorUpdateMode.Manual);
    print(anim.GetTimeUpdateMode());
     
    ModLunar likes this.
  2. DavidGeoffroy

    DavidGeoffroy

    Unity Technologies

    Joined:
    Sep 9, 2014
    Posts:
    542
    This is/will be used for something else (and is experimental, as evidenced by the enum name), and at the moment, doesn't do anything, as you saw.

    You can either disable the component, and update it manually.
    animator.enabled = false;
    then
    animator.Update(deltaTime);

    Or you can set the speed to zero, and do something like this when you want to update:
    animator.speed = 1.0f;
    animator.Update(deltaTime);
    animator.speed = 0.0f;

    Both will give slightly different results, and it depends what you want to do.
    The second one will animate every frame, but time will not advance.
    This also works with the state machine visual debugging, whereas disabling the animator will break the visual debugging.

    It's also worth noting that using any of those approaches means your animators will run single-threaded, so there may be performance issues.
     
    Hecocos, ModLunar, fum1 and 2 others like this.
  3. chadfranklin47

    chadfranklin47

    Joined:
    Aug 11, 2015
    Posts:
    229
    Could you elaborate a bit more on the Animator.Update being single threaded? Is the normal Animator Update method multithreaded? Would trying to optimize by using Animator.Update not be a good idea? Please help.
     
    futurlab_peterh likes this.
  4. DavidGeoffroy

    DavidGeoffroy

    Unity Technologies

    Joined:
    Sep 9, 2014
    Posts:
    542
    The normal Animator Update does one pass where it updates all the Animators, splitting these animators in batches that will be evaluated using all available threads.

    Calling Animator.Update will run the update for that Animator right away, so if you do this for all your Animators, then the other threads will sit idle in the meantime.

    If you are developing for PC, PS4, Xbox One or any platform that has multiple cores, it's unlikely that you'll be seeing any gains by manually updating the Animator.
     
    Alic and chadfranklin47 like this.
  5. chadfranklin47

    chadfranklin47

    Joined:
    Aug 11, 2015
    Posts:
    229
    Alright, thank you for clearing that up. I was hoping to save on some performance by changing the update rate of each Animator depending on the distance from the camera. I guess it would be useful if there was a method to add the Animator to a list of animators that are to update with the batch.
     
  6. DavidGeoffroy

    DavidGeoffroy

    Unity Technologies

    Joined:
    Sep 9, 2014
    Posts:
    542
    There's a clever user who figured out that you can put multiple animators in one PlayableGraph, connect an AnimatorControllerPlayable to each Animator, and then manually update the PlayableGraph.

    Doing this will execute the Animators as a batch, which will take advantage of all threads. It requires a bit more work than just dealing with the Animators directly, but it might address your use case.
     
    zhuchun, emptyxu, PedroCoriAG and 2 others like this.
  7. chadfranklin47

    chadfranklin47

    Joined:
    Aug 11, 2015
    Posts:
    229
    I have never heard of this. Thanks for letting me know, I will give it a shot.
     
    futurlab_peterh likes this.
  8. Justin_Larrabee

    Justin_Larrabee

    Joined:
    Apr 24, 2018
    Posts:
    106
    I implemented this technique as well and it feels like an abuse of the playables system. Is there any roadmap item for supporting batched update of a set of animator playables?
     
  9. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Did that user post about it somewhere publicly available? I have an entirely playables based system so I'm wondering if it would be worth changing my implementation. In particular, I'm wondering if Unity will multithread graphs containing PlayableBehaviours given that they don't seem to get multithreaded at the moment.
     
  10. Justin_Larrabee

    Justin_Larrabee

    Joined:
    Apr 24, 2018
    Posts:
    106
    Not that I'm aware of, I discovered it myself after some experimentation. I should note that I do not use any MonoBehaviours in my implementation as I am using the ECS and needed to avoid them.
     
    Alic likes this.
  11. LudiKha

    LudiKha

    Joined:
    Feb 15, 2014
    Posts:
    140
    @Justin_Larrabee do you have any information on how you did this? Would be much appreciated.
     
    Alic likes this.
  12. ZERO025

    ZERO025

    Joined:
    Jun 3, 2015
    Posts:
    5
    I put multiple animators in one PlayableGraph, and then execute Evaluate() in update.But as seen in the profile, PrepareFrame() can only be processed in the main thread.How can I make PlayableGraph.Evaluate execute multi-threaded?

    Code (CSharp):
    1. m_playableLod2.SetTimeUpdateMode(DirectorUpdateMode.Manual);
    2.  
    3. public AnimatorControllerPlayable RegisterLod(int index,Animator animator,RuntimeAnimatorController runtimeAnimatorController)
    4.     {
    5.         var animationOutput = AnimationPlayableOutput.Create(m_playableLod2, "Animation" + index, GetComponent<Animator>());
    6.         var ctrlPlayable = AnimatorControllerPlayable.Create(m_playableLod2, runtimeAnimatorController);
    7.         animationOutput.SetSourcePlayable(ctrlPlayable);
    8.         animationOutput.SetTarget(animator);
    9.         animator.runtimeAnimatorController = null;
    10.         return ctrlPlayable;
    11.     }
    12.  
    13.   private void Update()
    14.     {
    15.         m_playableLod2.Evaluate(Time.deltaTime);
    16.     }
    17.  
     

    Attached Files:

  13. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    I tried doing this (adding ~800 Animators to a PlayableGraph with the idea of controlling update frequency for performance).

    In profiling, with the graph being used, CPU-Animation gained ~2ms (from 7ms), Evaluating the graph added ~3-4ms (from 4ms) to CPU-Scripts that wasn't there previously.

    So ... huge loss of performance from implementing this with everything updating as frequently as it was previously.

    Splitting those 800 entities across two graphs and updating them alternately roughly brought performance back to where it was originally. Hrm.
     
  14. GloriaVictis

    GloriaVictis

    Joined:
    Sep 1, 2016
    Posts:
    133
    I am pretty new to the playable - but is there a way to use existing Mecanims and playables to exactly "lod them up", using PlayableGraphs to update them each "X" frames based on distance and that's it? Or I should be working on a custom implementation of Mecanim for that reason, making transitions and choosing clips from code for that reason?
     
  15. funkyCoty

    funkyCoty

    Joined:
    May 22, 2018
    Posts:
    727
    Could we please get some simple performance toggles for animators in general, very soon? The first two that come to mind:
    • being able to turn off animation interpolation/blending for things (LOD based? per-renderer, and let the LODGroup stuff handle it?)
    • being able to lower the tick rate (same as above, LOD based etc)
     
  16. Gulsnotten

    Gulsnotten

    Joined:
    Jan 24, 2017
    Posts:
    1
    I desperately need this exact functionality but have a hard time figuring out playables. Is there an example of this somewhere?
     
  17. ferrous

    ferrous

    Joined:
    Dec 31, 2012
    Posts:
    17
    @ZERO025 :
    I tried using your method of having a single playable graph, as it looked to be the cleanest. But I couldn't get it to work. The graph gets created, and it looks correct in the Visualizer, but my avatars wouldn't animate. We do use an AnimatorOverrideController? or could it be the version of Unity / AnimationRig? I'm on 2021.3.5f1, with Rigging version 1.1.1

    We're also using RigBuilder, so not sure if that might also be a source of complication.