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 handle animations correctly?

Discussion in 'Animation' started by Trotski94, Feb 20, 2014.

  1. Trotski94

    Trotski94

    Joined:
    Jan 7, 2014
    Posts:
    13
    I currently have a networked game I'm working on, and at first I had 2 RPCs for handling the animations, "Run()" and "Idle()", now this all worked fine until I tried throwing the attack animation into the works. I've spent hours reworking the code and now what I have left is a gargling mess of code which I doubt should ever be used, so I have decided to turn to here.

    Here is the basic layout for how I want the animations to work

    1. When stood still, the "Idle" animation plays
    2. Whilst moving, the "Run" animation plays
    3. When attacking, "Attack01" plays, but the function to hit only triggers when "Attack01" gets to a certain point in its run.

    Now when trying to implement this, I ran into 3 major problems: I Couldn't get it to blend properly, leaving me with a really choppy looking character; when the "Attack01" runs it was blending with the arm movements of either "Idle" or "Run", and when blended with "Idle" the result made it appear like the character was barely attacking at all due to Idles arm movements (similar problem with run but you can still tell the character is attacking); And I could not trigger the "hit" function on the enemy being attacked when the animation looked like it was actually hitting, only when the animation was triggered making the health drop just look early and weird.

    Here is the code I currently have to handle the animations, though I expect it is entirely wrong and someone will be able to provide better methods for what I'm doing. Possibly using functions for each "state" that can be called by RPC so every character doesnt have to control its own animations on every client.

    Code (csharp):
    1.     if (thePlayer!=null){
    2.  
    3.         if(Vector3.Distance(thePlayer.transform.position,transform.position) > 1.5f){
    4.                 agent.SetDestination(thePlayer.transform.position);
    5.                 if(animation["Idle"].weight > 0){
    6.                     animation.Blend("Idle", 0.0f, 0.3f);
    7.                 }
    8.                 if(animation["Run"].weight <= 0){
    9.                     animation.Blend("Run",1.0f,0.3f);
    10.                 }
    11.             }
    12.             else {
    13.                 agent.ResetPath();
    14.                 if(animation["Run"].weight > 0){
    15.                     animation.Blend("Run", 0.0f, 0.3f);
    16.                 }
    17.                 if(animation["Attack01"].weight <= 0  animation["Idle"].weight <= 0){
    18.                     animation.Blend("Idle",1.0f,0.3f);
    19.                 }
    20.             }
    21.  
    22.             if(Vector3.Distance(thePlayer.transform.position,transform.position) < 2.5f){
    23.                 if(hitCoolDown > 0.0f){
    24.                     hitCoolDown = hitCoolDown - (1.0f * Time.deltaTime);
    25.                 }
    26.                 else{
    27.                     //networkView.RPC("hitPlayer",RPCMode.AllBuffered,playerID,attackID);
    28.                     StartCoroutine(delayedHit(attackID));
    29.                     hitCoolDown = hitTime;
    30.                     if(animation["Idle"].weight > 0){
    31.                         animation.Blend("Idle", 0.0f, 0.3f);
    32.                     }
    33.                     if(animation["Attack01"].weight <= 0){
    34.                         animation.Blend("Attack01", 1.0f, 0.3f);
    35.                     }
    36.                 }
    37.             }
    38.             else if(animation["Attack01"].weight > 0){
    39.                 animation.Blend("Attack01", 0.0f, 0.3f);
    40.             }
    41.             if(animation["Attack01"].time > animation["Attack01"].length){
    42.                 if(animation["Attack01"].weight > 0.0f){
    43.                     animation.Blend("Attack01", 0.0f, 0.3f);
    44.                     animation.Blend("Idle", 1.0f, 0.3f);
    45.                 }
    46.                 else if (animation["Attack01"].weight == 0.0f){
    47.                     animation["Attack01"].normalizedTime = 0;
    48.                 }
    49.             }
    50.         }
    51.     }
    (I realise its probably an entirely wrong way of going about things)

    Now as you can probably see, I have
    Code (csharp):
    1. StartCoroutine(delayedHit(attackID));
    which is calling this function

    Code (csharp):
    1.     IEnumerator delayedHit(int ID){
    2.         yield return new WaitForSeconds(0.2f);
    3.         if(Network.isServer  attacking  attackID == ID){
    4.             GameObject thePlayer = getPlayerByID(attackID);
    5.             if(thePlayer != null){
    6.                 if(Vector3.Distance(thePlayer.transform.position,transform.position) < 2.5f){
    7.                     Debug.Log ("Hit");
    8.                     hitPlayer(playerID,attackID);
    9.                 }
    10.             }
    11.         }
    12.     }
    in an attempt to delay the hit function long enough that the animation looked like it hit when the "hit" is triggered in the code. This worked at first, but the "Attack01" animation loops endlessly rather than running once every time i hit, and if i changed its wrap mode to not loop when the animation ended it choppily jumped straight back to Idle or Run making it looks horrible, which is what the ugly method of

    Code (csharp):
    1.     if(animation["Attack01"].time > animation["Attack01"].length){
    2.         if(animation["Attack01"].weight > 0.0f){
    3.             animation.Blend("Attack01", 0.0f, 0.3f);
    4.             animation.Blend("Idle", 1.0f, 0.3f);
    5.         }
    6.         else if (animation["Attack01"].weight == 0.0f){
    7.             animation["Attack01"].normalizedTime = 0;
    8.         }
    9.     }
    is trying to handle... which almost works... almost.

    If anyone can point me in the direction of the correct method I should be using to accomplish this id be grateful, Thanks.