Search Unity

Control speed of transitions between animations in blend tree?

Discussion in 'Animation' started by Kaivian, Jul 7, 2019.

  1. Kaivian

    Kaivian

    Joined:
    Jan 18, 2018
    Posts:
    35
    The transitions are too sudden. Like, I want it to stay in the "blending" area for longer. Right now, I have it tied directly to input X. I tried a few things on my own (like clamping and averaging the previous value with the current value) in scripts, but it didn't really help it transition more smoothly, it still felt very sudden, just with a bit of a delay when it "snapped" to a different animation. It looks good if I play with the slider in the viewport, just not at runtime.

    upload_2019-7-7_12-54-22.png
     
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Blend trees don't transition over time, they go straight to the parameter value you set.

    You might be able to get the behaviour you want by using the overload of SetFloat that takes a dampTime, but otherwise you will need to change the value over time yourself.
     
    Kaivian likes this.
  3. Kaivian

    Kaivian

    Joined:
    Jan 18, 2018
    Posts:
    35
    Thank you! I followed a video tutorial online, but I don't think he really talked about that part, so when I tried to do something else, it didn't work!

    Here's the code I made. It works. Is this acceptable, or is there a better practice?


    Code (CSharp):
    1. public class PlayerController : MonoBehaviour
    2. {
    3.     //     public Boundary boundary;
    4.     public float speed;
    5.     public Animator animator;
    6.     private Rigidbody rb;
    7.     public float inputHorizontal;
    8.     public float inputVertical;    
    9.     public float recentHorizontal;      // avg horizontal movement over approx 50 frames
    10.     public float recentVertical;        // avg vertical movement over approx 50 frames
    11.                                         // 0 is 100%, -1 is stopped, 1 is 200%
    12.     void Start()
    13.     {
    14.         rb = GetComponent<Rigidbody>();
    15.         recentHorizontal = 0;
    16.     }
    17.  
    18.     void FixedUpdate()
    19.     {
    20.         inputHorizontal = Input.GetAxis("Horizontal");
    21.         inputVertical = Input.GetAxis("Vertical");
    22.  
    23.             // depriciates recent movement if no new movements are detected
    24.         recentVertical = Mathf.Clamp(inputVertical + (recentVertical / 1.04f), -1, 1);    
    25.             // small values are reset to 0
    26.         if (recentVertical < 0.1f && recentVertical > -0.1f)
    27.         {
    28.             recentVertical = 0;
    29.         }
    30.             // depriciates recent movement if no new movements are detected
    31.             // absolute value taken because animator does not allow 'less than' && 'greater than'
    32.         recentHorizontal = Mathf.Abs(Mathf.Clamp(((recentHorizontal / 1.04f) + (inputHorizontal)), -1, 1));
    33.             // small values are reset to 0
    34.         if (recentHorizontal < 0.1f)
    35.         {
    36.             recentHorizontal = 0;
    37.         }
    38.             // passes variables to animator, which blends stop/forward/backward/left/right animations based on recent inputs
    39.         animator.SetFloat("InputX", inputHorizontal);
    40.         animator.SetFloat("RecentVertical", recentVertical);
    41.         animator.SetFloat("RecentHorizontal", recentHorizontal);
    42.         Vector3 movement = new Vector3(inputHorizontal, 0.0f, inputVertical);
    43.         rb.MovePosition(transform.position + (movement * speed * Time.deltaTime));
    44.     }
    45. }
     
  4. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    That's a bit more complex than it needs to be. The clamps are unnecessary because the input will already be in that range and dividing by 1.04 is an awfully specific number which shouldn't be hard coded. Most of that logic could probably be replaced with simple Mathf.MoveTowards calls.
     
    Kaivian likes this.
  5. Kaivian

    Kaivian

    Joined:
    Jan 18, 2018
    Posts:
    35
    That's great feedback, thank you! Not to point fingers, but some of these youtube tutorials are a little iffy...
     
  6. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    The root of the problem is actually the Animator Controller system itself which makes it really hard to actually use effective programming practices in the first place. I've written more about the problems the system has in the documentation of my Animancer plugin (link in my signature).

    Also, I just noticed that you're setting your recent variables in the Animator as well, which is unnecessary. Just keep them in your own float fields, they don't actually serve any purpose as parameters (unless something in your controller is actually using them).