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

Blend Tree stuttering strafe/transsitions

Discussion in 'Animation' started by Salja, Jul 12, 2020.

  1. Salja

    Salja

    Joined:
    Mar 23, 2017
    Posts:
    353
    Hello there, we are experiencing some problems with our blend tree setup inside our Rootmotion Playercontroller. Our idle is outside of the walk/run blendtree and we are using start and stop motions. Everything is fine really, except for if you want to strafe from left to right too quick and especially when trying to transition from walking forward to backward and trice versa. It looks really stuttery and feels uncomfortable in those cases. We looked into the kubold playmaker controller and we are trying to copy it one by one just with C# code. Animator and transitions are all the same between us and theirs. It's a problem that has been bugging us for a while now with multiple playercontrollers, with the only way to fix this beeing to include the idle animation inside the walk blendtree, but for this project we want to know how it's really done. Any ideas?



    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class BasicPlayerController : MonoBehaviour
    6. {
    7.     #region Vabrialen
    8.  
    9.     // Grounded
    10.     public Collider mCharacterCollider;
    11.     public float mGroundedOffset = 0.1f;
    12.     float mDisstanceToTheGround;
    13.  
    14.     Animator mAnimator;
    15.     Transform mCamera;
    16.     Rigidbody mRigidbody;
    17.  
    18.     // Input Settings
    19.     float mHorizontal;
    20.     float mVertical;
    21.     float mRunFactor = 0.5f;
    22.  
    23.     float InputMagnitude;
    24.     float InputAngle;
    25.     Vector3 rDirection;
    26.  
    27.     bool IsFalling = false;
    28.  
    29.     #endregion
    30.  
    31.     #region Start
    32.  
    33.     private void Start()
    34.     {
    35.         mAnimator = this.GetComponent<Animator>();
    36.         mCamera = Camera.main.transform;
    37.         mRigidbody = this.GetComponent<Rigidbody>();
    38.  
    39.         if (mAnimator == null || mRigidbody == null ||
    40.             mCharacterCollider == null)
    41.             return;
    42.  
    43.         mAnimator.speed = 1.05f;
    44.         mAnimator.applyRootMotion = true;
    45.         mDisstanceToTheGround = mCharacterCollider.bounds.extents.y;
    46.     }
    47.  
    48.     #endregion
    49.  
    50.     #region Update
    51.  
    52.     private void Update()
    53.     {
    54.         CheckGrounded();
    55.         ControllerInput();
    56.     }
    57.     #endregion
    58.  
    59.     #region LateUpdate
    60.  
    61.     // Maybe FixedUpdate ???
    62.     void LateUpdate()
    63.     {
    64.         if (mAnimator == null || mCamera == null)
    65.             return;
    66.  
    67.         rDirection = new Vector3(mHorizontal, 0, mVertical);
    68.  
    69.         InputMagnitude = rDirection.magnitude;
    70.  
    71.         InputAngle = Vector2.SignedAngle(new Vector2(transform.forward.x, transform.forward.z), new Vector2(Camera.main.transform.forward.x, Camera.main.transform.forward.z));
    72.         InputAngle += Vector3.SignedAngle(transform.TransformVector(rDirection), transform.forward, Vector3.up);
    73.         InputAngle = InputAngle * -1;
    74.  
    75.         mAnimator.SetFloat("InputMagnitude", InputMagnitude *= mRunFactor);
    76.  
    77.         if (InputMagnitude > 0.2f)
    78.         {
    79.             RotateToCameraDirection(mCamera);
    80.  
    81.             mAnimator.SetFloat("WalkStartAngle", InputAngle);
    82.             mAnimator.SetFloat("WalkStopAngle", InputAngle);
    83.  
    84.             mAnimator.SetFloat("Horizontal", rDirection.x *= mRunFactor, 0.25f, Time.deltaTime);
    85.             mAnimator.SetFloat("Vertical", rDirection.z *= mRunFactor, 0.25f, Time.deltaTime);
    86.             mAnimator.SetFloat("InputAngle", InputAngle, 0.15f, Time.deltaTime);
    87.         }
    88.  
    89.         mAnimator.SetBool("IsFalling", !IsFalling);
    90.     }
    91.  
    92.     #endregion
    93.  
    94.     #region Functions
    95.  
    96.     private void RotateToCameraDirection(Transform mLookTransform)
    97.     {
    98.         Quaternion rotation = Quaternion.LookRotation(mLookTransform.forward);
    99.         rotation = new Quaternion(0.0f, rotation.y, 0.0f, rotation.w);
    100.  
    101.         transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * 5f);
    102.     }
    103.  
    104.     public bool CheckGrounded()
    105.     {
    106.         bool IsGrounded = Physics.Raycast(mCharacterCollider.bounds.center, Vector3.down, mDisstanceToTheGround + mGroundedOffset);
    107.         return IsFalling = IsGrounded;
    108.     }
    109.  
    110.     public void OnAnimatorMove()
    111.     {
    112.         Vector3 rootMotion = mAnimator.deltaPosition;
    113.         Vector3 currentVelocity = mRigidbody.velocity;
    114.         Vector3 animatorVelocity = rootMotion / Time.deltaTime;
    115.  
    116.         animatorVelocity.y = currentVelocity.y;
    117.         mRigidbody.velocity = animatorVelocity;
    118.  
    119.         Vector3 animatorAngularVelocity = mAnimator.angularVelocity;
    120.         mRigidbody.angularVelocity = animatorAngularVelocity;
    121.     }
    122.  
    123.     #endregion
    124.  
    125.     #region Input
    126.  
    127.     public void ControllerInput()
    128.     {
    129.         mHorizontal = Input.GetAxisRaw("Horizontal");
    130.         mVertical = Input.GetAxisRaw("Vertical");
    131.  
    132.         // Test Running
    133.         mRunFactor = Input.GetKey(KeyCode.LeftShift) ? mRunFactor = 2.0f : mRunFactor = 0.5f;
    134.     }
    135.  
    136.     #endregion
    137. }
    138.  
     
  2. dibdab

    dibdab

    Joined:
    Jul 5, 2011
    Posts:
    976
    hi, have you found the cause of this?
     
  3. Salja

    Salja

    Joined:
    Mar 23, 2017
    Posts:
    353
    No Not really i have try to start again with a Controller but i run all time in the same issue
     
  4. dibdab

    dibdab

    Joined:
    Jul 5, 2011
    Posts:
    976
    I noticed this can be betterd with input/blendtree parameter lerpin.

    seem to happen if the blendtree values change quickly, the com gets offset
    but still no answer what causes it. might be a bug in unity's com calculating

    okay, this is blending issue
    have you debug.log the blendtree input? this ? mRunFactor = 2.0f : mRunFactor = 0.5f; is it a value switch?
    but to me this anim looks like it always (or is it just while movin slow) goes back to idle
     
    Last edited: Jul 25, 2020