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

How to properly use OnAnimatorMove() without breaking timeline?

Discussion in 'Timeline' started by tarahugger, Dec 18, 2018.

  1. tarahugger

    tarahugger

    Joined:
    Jul 18, 2014
    Posts:
    129
    I have some code which i believe was from the 3rd person unity examples, and it implements OnAnimatorMove. In play mode, selecting an object and hitting the play/preview button in the timeline pane works and applies root motion just like if you had the inspector 'apply root motion' box checked. However in edit mode, it doesn't work, the animations play on the spot without root motion.

    The only work around right now for me seems to be to not use OnAnimatorMove(). Is this a bug with timeline? or is there another way to replicate the default functionality.?

    2018.3.0.0f2

    Code (CSharp):
    1.  
    2.     public void OnAnimatorMove()
    3.     {
    4.         if (Animator == null) return;
    5.  
    6.         Animator.ApplyBuiltinRootMotion();
    7.  
    8.         // we implement this function to override the default root motion.
    9.         // this allows us to modify the positional speed before it's applied.
    10.         if (_isGrounded && Time.deltaTime > 0)
    11.         {
    12.             Vector3 v = (Animator.deltaPosition * m_MoveSpeedMultiplier) / Time.deltaTime;
    13.  
    14.             // we preserve the existing y part of the current velocity.
    15.             v.y = m_Rigidbody.velocity.y;
    16.             m_Rigidbody.velocity = v;
    17.         }
    18.     }
    19.  
     
    Last edited: Dec 18, 2018
  2. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    That is related to the state machines, which, like physics, are not run in edit mode. Are you trying to define your own root motion? Is it deterministic?
     
  3. tarahugger

    tarahugger

    Joined:
    Jul 18, 2014
    Posts:
    129
    What i'm trying to do is setup some animation sequences in the timeline, but i would like it so that what i preview and tweak in edit mode is the same as what happens in play mode.

    There are three options for applying root motion, on, off and handled by script. The question was in other words, is there is a way to replicate the 'on' functionality when using 'handled by script' ? I had thought perhaps just calling ApplyBuiltinRootMotion() should do the trick. But it doesn't seem to work when it comes to how the timeline interacts with it.
     
  4. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    It works if you add the [ExecuteInEditMode] attribute to your script with OnAnimatorMove. Otherwise the OnAnimatorMove doesn't get called.
     
    pango likes this.
  5. tarahugger

    tarahugger

    Joined:
    Jul 18, 2014
    Posts:
    129
    Ahhh of course! thanks a lot!
     
  6. Storm4_

    Storm4_

    Joined:
    Mar 2, 2016
    Posts:
    14
    I have the same problem but with normal animations, sprite-based. In my case, the preview DID work without [ExecuteInEditMode], but only until 2019.1. Now with the attribute,
    transfom.position += animator.deltaPosition
    in my OnAnimatorMove works to preview things, but it seems to conflict with record mode, adding the delta position multiple times when I move the transform manually (upd: it does so even if I just edit the keyframe values). If I put
    ApplyBuiltInRootMotion()
    there instead, it does not do anything at all.
     
    Last edited: Apr 4, 2019
  7. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    Possibly the issue is evaluation occuring multiple times in editor without clearing the deltaPosition?

    Also, I can definitely see this having conflicts with recording. You may need to disable it while keyframing root motion.
     
  8. Storm4_

    Storm4_

    Joined:
    Mar 2, 2016
    Posts:
    14
    Turns out it didn't work properly because animator.applyRootMotion was false, even though that checkbox disappears and "Handled by script" is shown in its place if there's a component with OnAnimatorMove attached. Is this a bug? ApplyBuiltInRootMotion still does nothing, but adding deltaPosition now works perfectly even when recording.
     
  9. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    Yeah, that sounds like a UI bug with the animator inspector.
     
  10. thieum

    thieum

    Joined:
    Apr 8, 2011
    Posts:
    60
    Bumping into this with unity v.2019.2. I had previously worked with the Character Controller from the Standard Assets and Timeline back in v.2017.
    So I've been digging and it seems that, as long as OnAnimatorMove is being detected by the Animator (root motion = "handled by script"), Timeline won't apply the root motion nore the expected translations. Looks like a bug or regression...

    But if you change the callback and replace "OnAnimatorMove" with 'FixedUpdate" (as it's just about applying a velocity to the rigidbody), everything works fine!!!
    But it tooks me a couple of hours before I found the culprit and the hack.
    It's a pity that this Character controller can't be used with Timeline out of the box as it used to be.
     
    Last edited: Oct 14, 2019
    Malbers and mivasiliauskas like this.
  11. Malbers

    Malbers

    Joined:
    Aug 7, 2015
    Posts:
    2,558
    Hey @seant_unity
    Any news on this? I'm having the same problem ... any of my character.. if it uses OnAnimatorMove() I can't use the timeline and RootMotion Animations. :(

    BTW its 2021

    The only kind of hack I made on my scripts is:


    Code (CSharp):
    1. void OnAnimatorMove()
    2.         {
    3.             if (InTimeline)
    4.             {
    5.                 Anim.ApplyBuiltinRootMotion();
    6.                 return;
    7.       }
    8. }
    and I made an extra script for when I'm using the Timeline in the Editor:

    Code (CSharp):
    1. using UnityEngine;
    2. namespace MalbersAnimations.Controller
    3. {
    4.     [ExecuteInEditMode]
    5.     public class AnimatorMoveTimelineFixer : MonoBehaviour
    6.     {
    7.         public Animator anim;
    8.         void Start()
    9.         {
    10.             if (Application.isEditor && Application.isPlaying) Destroy(this);
    11.             anim = GetComponent<Animator>();
    12.         }
    13.  
    14.         private void OnAnimatorMove()
    15.         {
    16.             if (anim != null)
    17.                 anim.ApplyBuiltinRootMotion();
    18.         }
    19.  
    20.         private void Reset()
    21.         { anim = GetComponent<Animator>(); }
    22.     }
    23. }
    But again its a hack... a dirty solution :(

     
  12. hanbekov

    hanbekov

    Joined:
    Apr 1, 2017
    Posts:
    8
    hi folks!

    A version 2022.1.0.a has this bug again :((

    If I add OnAnimatorMove() (even with empty body) to gameobject script - the gameobject don`t move position by timeline, in editor mode and in game mode (character animation doing, but on one spot). If delete OnAnimatorMove() from gameobject scrip - the gameobject fine move by slider in timeline tab and in game.

    WTF???!
     
  13. tatoforever

    tatoforever

    Joined:
    Apr 16, 2009
    Posts:
    4,364
    Unity 2019.4.40f1 has this bug too. OnAnimatorMove won't get called if the GameObject holding the Animator is animated in Timeline.
     
  14. Zardify

    Zardify

    Joined:
    Jul 15, 2015
    Posts:
    20
    It feels like none of the bugs people actually struggle with get fixed... one has to have so many workarounds memorized it's insane.
     
    Whatever560 likes this.
  15. Whatever560

    Whatever560

    Joined:
    Jan 5, 2016
    Posts:
    505
    We should have a database of workarounds ...
     
    Alic and Yuchen_Chang like this.
  16. Whatever560

    Whatever560

    Joined:
    Jan 5, 2016
    Posts:
    505
    Somewhat related is the same issue I had with OnStateMove() implemented on State Machine Behaviour breaking timeline (even if it does nothing in the implementation): https://forum.unity.com/threads/timeline-animation-offset-is-broken.1438264/#post-9037885