Search Unity

Changing Character Animations

Discussion in 'Scripting' started by wrm186, Apr 23, 2017.

  1. wrm186

    wrm186

    Joined:
    Apr 4, 2010
    Posts:
    661
    Hey guys, it's been awhile since I have last posted as I've been making the journey through college for computer animation at Full Sail, and I decided to give another go at creating a game. I've got more knowledge on the topic of scripting this time, but still am pretty new to it. With that, I've been getting an error on this script that I've been following from Speed Tutor, but trying to make it fit my own needs. The main goal is just to switch states from an idle, walk, and run animations. More will be added later. I get an error as follows:

    "MissingComponetException: There is no 'Animatin' attatched to the "FPSArm" game object, but a script is trying to access it..."

    Then tells me I need to add an animation to it or have the script check to see if it is attached, here is the code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class FPSAnimation : MonoBehaviour {
    5.  
    6.     private CharacterController controller;
    7.     private Animation anim;
    8.  
    9.     // Use this for initialization
    10.     void Start ()
    11.     {
    12.         anim = GetComponent<Animation> ();
    13.         controller = GameObject.FindGameObjectWithTag("Player").GetComponent("CharacterController") as CharacterController;
    14.     }
    15.  
    16.     // Update is called once per frame
    17.     void Update ()
    18.     {
    19.         {
    20.             if (controller.velocity.magnitude <= 0)
    21.                 GetComponent<Animation> ().Play ("Idle");
    22.                 GetComponent<Animation> () ["Idle"].wrapMode = WrapMode.Loop;
    23.         }
    24.         if (controller.velocity.magnitude > 0 && Input.GetKey (KeyCode.LeftShift)) {
    25.             GetComponent<Animation> ().Play ("Run");
    26.             GetComponent<Animation> () ["Run"].wrapMode = WrapMode.Loop;
    27.         }
    28.         if (controller.velocity.magnitude > 0 && Input.GetKey (KeyCode.W)) {
    29.             GetComponent<Animation> ().Play ("Walk");
    30.             GetComponent<Animation> () ["Walk"].wrapMode = WrapMode.Loop;
    31.         }
    32.     }
    33. }
    Now, I do have an Animator on the "FPSArm" with the states all properly named and conditioned correctly, and this script is attached to the "FPSArm" as well. I feel like I am possibly referencing the wrong thing for "private Animation anim;" as that is only referencing one animation, correct? Instead of the Animator, which has three animations.

    If you happen to take your time to read this, and possibly respond, thank you! It's greatly appreciated as I am sure that I have possibly worded this confusingly!
     
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I saw a somewhat similar post a while back, and believe that animation is older and animator is newer (which has the animations inside it , as you described). Anyways, whether that's true or not is not super important. I believe you are correct with wanting to access the animator, instead. In my very little experience, that's what I always used.
    With the component referenced, you can set values/triggers etc that will alter states/do your animations.
    Hopefully that's enough info to get you pointed in the right direction for now.
     
  3. wrm186

    wrm186

    Joined:
    Apr 4, 2010
    Posts:
    661
    Hey, anything will help! I wasn't really expecting a reply really, so thanks for your input! I'll give it another go and see what I can come up with.
     
  4. wrm186

    wrm186

    Joined:
    Apr 4, 2010
    Posts:
    661
    Well I messed around a little more, instead of using the Animator component on my arms, I used the Animation component. Dropped all three animations into it, and it works... for the most part. The only thing that's not working now is the Run animation. The arms stays stiff while holding shift, but letting go plays the walk and idle animations no problem. Any idea what might be causing this?

    Is it possibly because the walk and run animation is wanting a value greater than 0? But then again, I am also saying to get the specific KeyCode also... so I don't know haha.
     
  5. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I've never used animation directly, myself. In the animator, I have only ever had a simple setup with idle , walk, run, and jump. I would set triggers to change states. I know there are other ways. Maybe someone else will see your post and offer some feedback. Good luck :)
     
  6. wrm186

    wrm186

    Joined:
    Apr 4, 2010
    Posts:
    661
    Ah, alright no problem, well thank you very much for your help!
     
  7. wrm186

    wrm186

    Joined:
    Apr 4, 2010
    Posts:
    661
    Bump.
    I think I sort of found the problem, but not sure how to fix it.
    The run animation works while holding shift and the "S" key, but not the "W" key (this is when the animation freezes in place).
    I tried adding adding another KeyCode at the end of the command like this:

    Code (CSharp):
    1. if (controller.velocity.magnitude > 0 && Input.GetKey (KeyCode.LeftShift) && (KeyCode.W)))
    2.  {
    3.             GetComponent<Animation> ().Play ("Run");
    4.             GetComponent<Animation> () ["Run"].wrapMode = WrapMode.Loop;
    5. }
    As well as:
    Code (CSharp):
    1. if (controller.velocity.magnitude > 0 && Input.GetKey (KeyCode.LeftShift))
    2. {
    3. if Input.GetKeyDown (KeyCode.W)
    4. {
    5.             GetComponent<Animation> ().Play ("Run");
    6.             GetComponent<Animation> () ["Run"].wrapMode = WrapMode.Loop;
    7. }
    But still no luck.
     
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I don't think this syntax is correct.
    Code (CSharp):
    1. && Input.GetKey (KeyCode.LeftShift) && (KeyCode.W)))
    2. // would be instead
    3. && Input.GetKey(KeyCode.W)
    4.  
    I am a little confused why you have to check the velocity, because I am guessing that those keys make the controller move and they would have to be pressed already. Not that that's really an issue, just a thought.

    Just curious: why is 's' working but not 'w' ? :)
     
  9. wrm186

    wrm186

    Joined:
    Apr 4, 2010
    Posts:
    661
    I'll give it a shot and see how it works! Thanks! :)

    And well if I'm not mistaking, I think the velocity gets the players "speed", and once it reaches that certain velocity (or speed) it will play that animation.

    As for working with S and not W, I am clueless haha. I think it has something to do with the W key already being referenced? And since I'm still holding down the Shift key while then holding S, it plays the run animation normally. So I think I need a way to have it reference once both keys are pressed, but the two ways I know how did not work apparently (didn't get an error though). I am going to try one more thing later tonight and see if it works.
     
  10. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I figured you wanted to check the speed to see if the player was moving, but I guess my question/comment was that you're probably using the 'w' and 's' keys, etc.. to move the player in the first place, so you can safely assume it's moving. That would be slightly different for 'run' , true.
    Anyways, we'll see what your further experiments reveal :)
     
  11. wrm186

    wrm186

    Joined:
    Apr 4, 2010
    Posts:
    661
    I FINALLY got it to work! :D

    I think the problem as to why the run animation "froze" when triggered, is because the walk and run animations were basically overlapping each other. Because both were told to "play" if the velocity is greater than 0. So, the solution (well whats working for me) is changing the ".Play" to ."CrossFade". Thus not making the two animation play at the same time (I'm assuming). Here is the script if anyone else possibly has had this same problem:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class FPSAnimation : MonoBehaviour {
    5.  
    6.     private CharacterController controller;
    7.     private Animation anim;
    8.  
    9.  
    10.     // Use this for initialization
    11.     void Start ()
    12.     {
    13.         anim = GetComponent<Animation> ();
    14.         controller = GameObject.FindGameObjectWithTag("Player").GetComponent("CharacterController") as CharacterController;
    15.     }
    16.    
    17.     // Update is called once per frame
    18.     void Update ()
    19.     {
    20.        
    21.         if (controller.velocity.magnitude <= 0)
    22.         {
    23.             GetComponent<Animation> ().CrossFade ("Idle");
    24.             GetComponent<Animation> () ["Idle"].wrapMode = WrapMode.Loop;
    25.         }
    26.  
    27.         if (controller.velocity.magnitude > 0 && Input.GetKey(KeyCode.W))
    28.         {
    29.             GetComponent<Animation> ().CrossFade ("Walk");
    30.             GetComponent<Animation> () ["Walk"].wrapMode = WrapMode.Loop;
    31.         }
    32.         if (controller.velocity.magnitude > 0 && Input.GetKey(KeyCode.LeftShift))
    33.         {
    34.             GetComponent<Animation> ().CrossFade ("Run");
    35.             GetComponent<Animation> () ["Run"].wrapMode = WrapMode.Loop;
    36.         }
    37.     }
    38. }
    I do still get a warning saying
    "The private feild 'FPSAnimation.anim' is assigned but its value is never used."

    Nonetheless, it still works :)
     
  12. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Cool, glad ya got it working, one way or another :)
    Code (CSharp):
    1. // your code like this .. stores the variable.
    2. anim = GetComponent<Animation>();
    3.  
    4. // but later, you keep looking it up , again with:
    5. GetComponent<Animation>(). // etc
    6. // which you can swap to:
    7. anim.CrossFade("Run"); // or whatever. :)
     
  13. wrm186

    wrm186

    Joined:
    Apr 4, 2010
    Posts:
    661
    oh okay, so instead of writing it like:
    Code (CSharp):
    1.  
    2. GetComponent<Animation> ().CrossFade ("Idle");
    3. GetComponent<Animation> () ["Idle"].wrapMode = WrapMode.Loop;
    4.  
    I can write it like:

    Code (CSharp):
    1.  
    2. anim.CrossFade ("Idle");
    3. anim ["Idle"].wrapMode = WrapMode.Loop;
    4.  
    Or am I misunderstanding this? :)
     
  14. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    No, that's right. See how you assign the variable in the Start method?
    Not like a super huge deal in this case.. just thought I'd point it out :)
     
  15. wrm186

    wrm186

    Joined:
    Apr 4, 2010
    Posts:
    661
    Ah, well thank you for telling me that. I changed it and it worked, better to do it that way so you don't have to write as much code! I just keep learning new things :) thanks for your help by the way!
     
  16. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    heh, np. Yes, writing less is a bonus. And the small performance benefit. (Usually stands out in more intensive use/frequency of updates, etc..)

    Anyhow, you're most welcome. Cheers.