Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Crossfading run and idle

Discussion in 'Scripting' started by rmele09, Mar 12, 2015.

  1. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    688
    I am not sure what is wrong with this code. I am using the first person controller, with a character mesh parented to it with its own rigidbody, collider and script. I want the character to play the Idle animation when the rigidbody is not moving, and then crossfade into the run animation when you start moving by hitting "w". Right now, game starts and Idle starts looping like supposed to. When you hit "w" the character starts moving but is always still playing the Idle animation, so it is not crossfading into the run animation. I am not sure if I am using the rigidbody.velocity correctly, I used it this way in a 2.5d game but never before in 3d. Or maybe I am setting up the character wrong?? Both run and idle animations are on layer 0, tried adjusting that but it doesn't help. Here is the code:
    EDIT: To be clear, the character continues to play the idle animation on loop.
    Code (JavaScript):
    1. function Update ()
    2. {
    3. // Play Animations
    4. // Idle
    5. if (GetComponent.<Rigidbody>().velocity.z == 0 && GetComponent.<Rigidbody>().velocity.x == 0)
    6. {
    7.     GetComponent.<Animation>().CrossFade("playerIdle");
    8. }
    9. // Run
    10. if (Input.GetButtonDown("Run"))
    11. {
    12.     GetComponent.<Animation>().CrossFade("playerRun");
    13. }
    14.  
    15. } // End Update
     
    Last edited: Mar 12, 2015
  2. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    688
  3. HotPhone

    HotPhone

    Joined:
    May 14, 2014
    Posts:
    53
    Is your rigidbody moving when you press "Run"? That code looks like when you press run, it starts crossfading to RUN animation, but one frame later it starts crossfading to idle animation again, because the velocity is 0. Store the components as fields, it is faster. I always use the animator controller, maybe you should try it out. That way, you don't need to bother about starting animations, you only pass the conditions.

    EDIT:

    Sorry, you already said, that the character was moving. Here are two things you could try:

    /// Check if Run animation even starts:
    1. function Update ()
    2. {
    3. // Play Animations
    4. // Idle
    5. if (GetComponent.<Rigidbody>().velocity.z == 0 && GetComponent.<Rigidbody>().velocity.x == 0)
    6. {
    7. GetComponent.<Animation>().CrossFade("playerIdle");
    8. }
    9. // Run
    10. if (Input.GetButtonDown("Run"))
    11. {
    12. GetComponent.<Animation>().CrossFade("playerRun");
    13. Debug.Log(GetComponent.<Animation>().IsPlaying("playerRun");
    14. }

    15. } // End Update
    or:

    // Setting the animations without using velocity:
    • function Update ()
    • {
    • // Play Animations
    • if (Input.GetButtonDown("Run"))
    • {
    • GetComponent.<Animation>().CrossFade("playerRun");
    • Debug.Log(GetComponent.<Animation>().IsPlaying("playerRun");
    • }
    • if (Input.GetButtonUp("Run"))
    • {
    • GetComponent.<Animation>().CrossFade("Idle");
    • Debug.Log(GetComponent.<Animation>().IsPlaying("Idle");
    • }
    • }
     
    Last edited: Mar 12, 2015
  4. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    688
    Interestingly enough, when I use the debugger how you did in your first suggestion, the console says True, that Run is playing. When clearly, Idle is playing. What do you think of that?
     
  5. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    688
    This still does not stop the Idle:

    GetComponent.<Animation>().CrossFade("Run");
    GetComponent.<Animation>().Stop("Idle");
    Debug.Log(GetComponent.<Animation>().IsPlaying("Run"));
     
  6. roger0

    roger0

    Joined:
    Feb 3, 2012
    Posts:
    1,208
    Try using debug.log to see if the idle animation is being called as well when the run animation is being called. I dont think the player controller would effect the velocity of the rigid body because the controller is not physics based, so the idle animation could be being called all the time because the velocity is remaining at 0.
     
  7. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    688
    Could it be that I am using the first person controller, which uses a character controller. Then I have the character mesh that has a rigidbody and capsule collider parented to the controller? Would that interfere even though the script is on the mesh itself? The reason I am doing this is because I have a third-person body and first-person arms both parented to the character controller for movement.
     
  8. roger0

    roger0

    Joined:
    Feb 3, 2012
    Posts:
    1,208
    I dont think it matters, although, the character controller does not use physics, so I dont think it would be adding velocity to the rigidbody when it moves. You could try using Input.GetKeyUp("Run") instead of checking the velocity in order to play the idle animation.

    Code (CSharp):
    1. function Update ()
    2. {
    3. // Play Animations
    4. // Idle
    5. if (Input.GetKeyUp("Run"))
    6. {
    7.     GetComponent.<Animation>().CrossFade("playerIdle");
    8. }
    9. // Run
    10. if (Input.GetButtonDown("Run"))
    11. {
    12.     GetComponent.<Animation>().CrossFade("playerRun");
    13. }
    14.  
     
  9. XenoJester

    XenoJester

    Joined:
    Feb 25, 2015
    Posts:
    13
    I have a similar set up. You have to use characterController.velocity. The rigidbody.velocity wont work with controllers.
     
  10. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    688
    1.png XenoJester, that makes sense. But I am getting the error below because the character controller is not on my actual mesh. The picture I uploaded shows how I have this setup, as follows:
    Vidar_Player is the parent and has the character controller on it.
    VidarMesh has the script with all of my logic on it, (and the rigidbody) because the animation are on this mesh as well. I tried putting the animations on the parent, but it would not work.
    I would also like to note that Vidar_Player is the first person controller renamed, and then I added my first person arms (parented to first person character) and third person mesh (vidarMesh) because the animations are separate.

    Error:
    There is no 'CharacterController' attached to the "VidarMesh" game object, but a script is trying to access it.

    Is there a different way I need to set this all up?
     
  11. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    688
    I feel like I have to take all of the components on Vidar_Player and apply them to VidarMesh and make that the parent? Does that sound correct?
     
  12. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    688
    I tried this out, and it works. However, now my first person arms rotate all crazy because they dont stop when rotating upwards anymore. Clamp vertical rotate on the first person controller script behaves strangely now. They just keep rotating in a circle and it throws everything off....
     
    Last edited: Mar 14, 2015
  13. roger0

    roger0

    Joined:
    Feb 3, 2012
    Posts:
    1,208
    Try out the method I suggested. It's a simpler solution and wont require getting the velocity of the controller.
     
  14. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    688
    I tried the method out last night, thank you for the suggestion. The issue with that method is that it causes inaccuracy with timing of the crossfades. Because if I am playing idle on buttonUp, that means I have to do that with every strafe, rotate, run etc. In this game, you are constantly moving. I tried it out and the animations do not switch fast enough to offer the realism that the game requires. When I got it working with the character controller velocity, the timing is perfect. Now I have this new issue of the arms rotating crazy. I don't understand why being parented to a mesh or essentially an empty game object like the first person controller would affect the clamp vertical effectiveness but it is :(
     
  15. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    688
    I dont know maybe im just being a perfectionist, I'll just use that method for now. The difference is probably in my mind lol. Thanks a bunch and if anybody else wants to chime in on the other method above feel free.
     
  16. XenoJester

    XenoJester

    Joined:
    Feb 25, 2015
    Posts:
    13
    Well you know you can pass references around, it doesn't really matter where the script lives. You could reference your character controller by going CharacterController myController = transform.root.getcomponent<CharacterController>(); From a script living on vidarMesh, transform.root would be the Vidar_Player.

    All in all it does seem like your hierarchy is messed up. I don't see why a rigidbody would be on your third person mesh. The collider and rigidbody should be on the root object (vidar_player). Your mesh should just be a mesh and animator, nothing more. Also you should parent your first person arms mesh to the MainCamera (not sure where that is). A simple solution is to have a default mouseLook script on the root player for left and right turning, and a mouseLook on the camera for up and down.
     
  17. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    688
    So in javascript does it look something like this:

    function Update () {
    var vidarPlayer = GameObject.FindWithTag("Vidar_Player").transform;
    var myController = vidarPlayer.GetComponent.<CharacterController>();
    }

    Then to access the character controller velocity, would I write:
    myController.velocity

    ?
     
    Last edited: Mar 20, 2015
  18. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    688
    Yes! I got this working finally. XenoJester thank you for that last post, I didn't know you could access the controller that way!