Search Unity

Issues with applying root motion

Discussion in 'Animation' started by AnimusRex, Apr 28, 2020.

  1. AnimusRex

    AnimusRex

    Joined:
    Apr 26, 2019
    Posts:
    67
    I'm trying to apply root motion for attack animations, but not other animations.

    Doing debug logs, my anim.deltaPosition is always 0,0,0, and my root motion is always off, and I can't figure out why.

    Here is my StateManager:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using InControl;
    5.  
    6. namespace KM
    7. {
    8.     public class StateManager : MonoBehaviour
    9.     {
    10.         [Header("Init")]
    11.         public GameObject activeModel;
    12.  
    13.         [Header("Inputs")]
    14.         public float vertical;
    15.         public float horizontal;
    16.         public float moveAmount;
    17.         public Vector3 moveDir;
    18.         public bool l1, l2, r1, r2;
    19.         public bool twoHanded;
    20.  
    21.         [Header("Stats")]
    22.         public float moveSpeed = 2f;
    23.         public float runSpeed = 3.5f;
    24.         public float rotateSpeed = 8f;
    25.         public float toGround = 0.5f;
    26.  
    27.         [Header("States")]
    28.         public bool onGround;
    29.         public bool run;
    30.         public bool lockOn;
    31.         public bool inAction;
    32.         public bool canMove;
    33.         public bool isTwoHanded;
    34.  
    35.         [HideInInspector]
    36.         public AnimatorHook a_hook;
    37.         [HideInInspector]
    38.         public Animator anim;
    39.         [HideInInspector]
    40.         public Rigidbody rigid;
    41.         [HideInInspector]
    42.         public float delta;
    43.         [HideInInspector]
    44.         public LayerMask ignoreLayers;
    45.  
    46.         float _actionDelay;
    47.  
    48.         public void Init()
    49.         {
    50.             SetupAnimator();
    51.  
    52.             rigid = GetComponent<Rigidbody>();
    53.             rigid.angularDrag = 999;
    54.             rigid.drag = 4;
    55.             rigid.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
    56.  
    57.             a_hook = activeModel.AddComponent<AnimatorHook>();
    58.             a_hook.Init(this);
    59.  
    60.  
    61.             gameObject.layer = 8;
    62.             ignoreLayers = ~(1 << 9);
    63.  
    64.             anim.SetBool("onGround", true);
    65.         }
    66.  
    67.         void SetupAnimator()
    68.         {
    69.             if (activeModel == null)
    70.             {
    71.                 anim = GetComponentInChildren<Animator>();
    72.                 if (anim == null)
    73.                 {
    74.                     Debug.Log("You're a dingus, there's no model");
    75.                 }
    76.                 else
    77.                 {
    78.                     activeModel = anim.gameObject;
    79.                 }
    80.             }
    81.  
    82.             if (anim == null)
    83.                 anim = activeModel.GetComponent<Animator>();
    84.  
    85.  
    86.             anim.applyRootMotion = false;
    87.         }
    88.  
    89.         public void FixedTick(float d)
    90.         {
    91.             delta = d;
    92.  
    93.             DetectAction();
    94.  
    95.             if (inAction)
    96.             {
    97.                 _actionDelay += delta;
    98.                 if(_actionDelay > 0.3f)
    99.                 {
    100.                     inAction = false;
    101.                     _actionDelay = 0;
    102.                 }
    103.                 else
    104.                 {
    105.                     return;
    106.                 }
    107.             }
    108.  
    109.             canMove = anim.GetBool("can_move");
    110.  
    111.             if (!canMove)
    112.             {
    113.                 return;
    114.             }
    115.  
    116.             anim.applyRootMotion = false;
    117.  
    118.             rigid.drag = (moveAmount > 0 || onGround == false) ? 0 : 4;
    119.  
    120.             float targetSpeed = moveSpeed;
    121.             if (run)
    122.                 targetSpeed = runSpeed;
    123.  
    124.             if(onGround)
    125.             rigid.velocity = moveDir * (targetSpeed * moveAmount);
    126.  
    127.             if (run)
    128.                 lockOn = false;
    129.  
    130.             if (!lockOn)
    131.             {
    132.                 Vector3 targetDir = moveDir;
    133.                 targetDir.y = 0;
    134.                 if (targetDir == Vector3.zero)
    135.                     targetDir = transform.forward;
    136.                 Quaternion tr = Quaternion.LookRotation(targetDir);
    137.                 Quaternion targetRotation = Quaternion.Slerp(transform.rotation, tr, delta * moveAmount * rotateSpeed);
    138.                 transform.rotation = targetRotation;
    139.             }
    140.  
    141.             HandleMovementAnimations();
    142.         }
    143.  
    144.         public void DetectAction()
    145.         {
    146.             if (!canMove)
    147.                 return;
    148.  
    149.             if (!r1 && !r2 && !l1 && !l2)
    150.                 return;
    151.  
    152.             string targetAnim = null;
    153.  
    154.             if (r1)
    155.                 targetAnim = "oh_attack_1";
    156.             if (r2)
    157.                 targetAnim = "oh_attack_3";
    158.             if (l1)
    159.                 targetAnim = "oh_attack_1";
    160.             if (l2)
    161.                 targetAnim = "oh_attack_2";
    162.  
    163.             canMove = false;
    164.             inAction = true;
    165.             anim.CrossFade(targetAnim, 0.2f);
    166.         }
    167.  
    168.         public void Tick(float d)
    169.         {
    170.             delta = d;
    171.             onGround = OnGround();
    172.  
    173.             anim.SetBool("onGround", onGround);
    174.         }
    175.  
    176.         void HandleMovementAnimations()
    177.         {
    178.             anim.SetBool("run", run);
    179.             anim.SetFloat("vertical", moveAmount, 0.4f, delta); //Only vertical because no lock on mode
    180.         }
    181.  
    182.         public bool OnGround()
    183.         {
    184.             bool r = false;
    185.  
    186.             Vector3 origin = transform.position + (Vector3.up * toGround);
    187.             Vector3 dir = -Vector2.up;
    188.             float dis = toGround + 0.3f;
    189.  
    190.             RaycastHit hit;
    191.  
    192.             if(Physics.Raycast(origin, dir, out hit, dis, ignoreLayers))
    193.             {
    194.                 r = true;
    195.                 Vector3 targetPosition = hit.point;
    196.                 transform.position = targetPosition;
    197.             }
    198.  
    199.             Debug.DrawRay(origin, dir, Color.red);
    200.  
    201.             return r;
    202.         }
    203.  
    204.         public void HandleTwoHanded()
    205.         {
    206.             anim.SetBool("two_handed", isTwoHanded);
    207.         }
    208.     }
    209. }
    210.  
    211.  
    Here is my AnimatorHook:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace KM
    6. {
    7.     public class AnimatorHook : MonoBehaviour
    8.     {
    9.         Animator anim;
    10.         StateManager states;
    11.  
    12.         public void Init(StateManager st)
    13.         {
    14.             states = st;
    15.             anim = st.anim;
    16.         }
    17.  
    18.         void OnAnimatorMove()
    19.         {
    20.             Vector3 DeltaPosition = anim.deltaPosition;
    21.             Vector3 OriginalVelocity = states.rigid.velocity;
    22.  
    23.             Vector3 SetVelocity = DeltaPosition / Time.deltaTime;
    24.  
    25.             //Add new velocity
    26.             states.rigid.velocity = SetVelocity;
    27.         }
    28.  
    29.         void OpenDamageColliders()
    30.         {
    31.  
    32.         }
    33.  
    34.         void CloseDamageColliders()
    35.         {
    36.  
    37.         }
    38.     }
    39. }
    40.  
    41.  
    Any insight appreciated. I see that some things with OnAnimatorMove() seem to have changed, but I can't for the life of me get this working.
     
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    OnAnimatorMove ignores the applyRootMotion flag, so if you want it to stop applying movement then its up to you to set the velocity to zero.

    But if you are never getting any delta position, then the problem is probably one of the options in the animation import settings.
     
    moungoslukas likes this.
  3. AnimusRex

    AnimusRex

    Joined:
    Apr 26, 2019
    Posts:
    67
    upload_2020-4-27_23-34-1.png

    Here's an example of the settings all the attack anims use. If I check root transform position for XZ, they do use root motion during the attack, but then after the attack they slide back to their original position, which is what the animator hook was to account for based on my understanding of it, I want it to end with the rigidbody and capsule collider where the animation ended.

    Additionally, my set up of GOs is
    PlayerController parent with rigidbody, capsule collider, statecontroller
    >Character itself with skinned mesh renderer and animator
     
    krearthur likes this.
  4. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I'm not sure then. That looks like the settings I would use, though I don't use root motion much.
     
  5. KingHL

    KingHL

    Joined:
    Jun 2, 2022
    Posts:
    2
    I know this an old post but did you ever find the solution for this?