Search Unity

Position control using OnAnimatorMove()

Discussion in 'Animation' started by augustinus, Sep 8, 2017.

  1. augustinus


    Feb 3, 2015
    I am trying to control character's position at OnAnimationMove method.

    "Apply Root Motion" option is controlled on scripts.
    And 'Walk' animation move (1, 0, 0) meter exactly in 3ds Max.

    So, when animator state become "Walk", I added the _animator.deltaPosition to character position.
    But, everytime I play the animation, the total movement differ from 3ds Max movement.

    Not, (1, 0, 0)
    sometimes, it's (1.1, 0, 0), then, (0.99, 0, 0), (1.01, 0, 0), (1.2, 0, 0) ...

    I think because OnAnimatorMove can not run for the exact time duration of "Walk",
    the result movement differ from original animation movement.

    I want to move the character the same as original animation movement exactly.
    It there any solution about this problem?

    Code (CSharp):
    2.     void OnAnimatorMove()
    3.     {
    4.         AnimatorStateInfo stateInfo = _animator.GetCurrentAnimatorStateInfo(0);
    5.         if(stateInfo.fullPathHash == HashWalk)
    6.         {
    7.                _tr.position += _animator.deltaPosition;
    8.                _tr.forward = _animator.deltaRotation * _tr.forward;
    9.         }
    10.     }
    Last edited: Sep 8, 2017
  2. Mecanim-Dev


    Unity Technologies

    Nov 26, 2012
    If you want precise movement of your character you will need to use another method than root motion.

    Animation driven root motion is sensible to frame rate because the animation is sampled with a variable deltaTime at each frame which yield a delta position/rotation that is cumulated with the current root transform.

    You can improve the presicion of root motion by setting your animator update mode to Animate physics, this way the sampling rate is more constant because you always sample the animation with a fixed delta time but still as soon as you start to blend animation clip togheter the root motion is also blended so you will lose some precision.

    Another way would be to use those 3 undocumented member and apply it manually on your transform in OnAnimatorMove
    float AnimationClip.averageDuration
    float AnimationClip.averageAngularSpeed -> Deg/sec
    Vector3 AnimationClip.averageSpeed -> Meter/sec

    You can see those value in the inspector when you select a clip, if they don't fit the value that you are expecting then you will need to build your own clip velocity data
    florianhanke, XiaGu and nirvanajie like this.
  3. CherstvyDmitriy


    Jul 19, 2017
    Hi , ia have a question.

    How can i move capsule(animator) as moves player? (See on screenshot)

    Attached Files:

  4. Baste


    Jan 24, 2013
    I hit on this thread from google now, and I wanted to shoot in a quick update. averageAngularSpeed does not give Deg/sec, it gives Rad/sec.

    Any chance you could document these features? Any reason they're undocumented?