2
votes

I'm trying to control a set of character animations but I'm having trouble with the jump animations. My horizontal walk animations are working fine but when I hit the jump button I want one of two jump animations to play depending on whether the player is in an idle or walking state. However when I press the jump button currently it only plays the first frame of the respective jump animation and then goes right back to either idle or walk. How do I get the entire jump animation to play when the jump button is pressed?

using UnityEngine;
using System.Collections;

public class AsherBlackMover : MonoBehaviour {

    public float moveSpeed = 3;
    public float rotateSpeed = 10;
    public Transform graphics;
    public SkeletonAnimation skeletonAnimation;
    public Vector2 jumpVector;
    public bool isGrounded;

    // isGrounded Variables
    public Transform grounderPosition;
    public float grounderRadius;
    public LayerMask grounderLayerMask;

    private Rigidbody2D asherBlackRB;
    private Animator asherBlackAnim;

    Quaternion goalRotation = Quaternion.identity;
    float xDir;
    float yDir;
    string currentAnimation = "";

    void Start ()
    {
        // Create a reference to Asher Black Rigidbody2D
        asherBlackRB = GetComponent<Rigidbody2D>();
    }

    void Update ()
    {
        xDir = Input.GetAxis ("Horizontal") * moveSpeed;

        if (xDir > 0) // ------ Walk Right
        {
            goalRotation = Quaternion.Euler (0, 0, 0);
            SetAnimation ("Walk", true);
        } 
        else if (xDir < 0) // ------ Walk Left
        {
            goalRotation = Quaternion.Euler (0, 180, 0);
            SetAnimation ("Walk", true);
        }
        else if (isGrounded == true) // ------ Idle
        {
            SetAnimation ("Idle", true);
        }

        // Jump Button
        if (Input.GetKeyDown("space") && isGrounded == true)
        {
            isGrounded = false;

            if (xDir > 0)
            {
                Jump ("Walk-Jump");
            }
            else if (xDir < 0)
            {
                Jump ("Walk-Jump");
            }
            else
            {
                Jump ("Idle-Jump");
            }
        }

        // Circle on character that determines when grounded or not
        isGrounded = Physics2D.OverlapCircle (grounderPosition.transform.position, grounderRadius, grounderLayerMask);

        // Flip character smothly to emulate paper mario effect
        graphics.localRotation = Quaternion.Lerp (graphics.localRotation, goalRotation, rotateSpeed * Time.deltaTime);
    }

    void OnDrawGizmos ()
    {
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireSphere (grounderPosition.transform.position, grounderRadius);
    }

    void SetAnimation (string name, bool loop)
    {
        if (name == currentAnimation)
        {
            return;
        }
        skeletonAnimation.state.SetAnimation (0, name, loop);
        currentAnimation = name;
    }

    void Jump (string animationName)
    {
        asherBlackRB.AddForce (jumpVector, ForceMode2D.Force);
        SetAnimation (animationName, true);
    }

    // Physics Updates
    void FixedUpdate ()
    {
        asherBlackRB.velocity = new Vector2 (xDir, asherBlackRB.velocity.y);
    }
}
2

2 Answers

2
votes

Your jumping animations don't display correctly because you're always changing it back to another animation the very next frame. For instance, with idling:

else
{
    SetAnimation ("Idle", true);

    if (Input.GetKeyDown("space"))
    {
        SetAnimation ("Idle-Jump", true);
    }
}

Every frame the character is idle, the idle animation will be set regardless of whether the character is jumping or not. But, as long as the space bar is held down, it will be swapped back to the first frame of the jumping animation.

You should probably have a Boolean that indicates when the character is jumping. You set it to true any time you set the character to the jumping animation. And then you can adjust your if statements so that the first thing it handles is the character in a jumping state, so that your jumping logic can complete without anything interfering. When the character is done jumping, you set the Boolean back to false. So, something like:

bool jumping = false;

// User Input
void Update ()
{
    xDir = Input.GetAxis ("Horizontal") * moveSpeed;

    if (jumping)
    {
        // Process jumping here
        if (/* Check for jumping finished here */)
        {
            // Finished jumping
            jumping = false;
        }
    }
    else if (xDir > 0)
    {
        goalRotation = Quaternion.Euler (0, 0, 0);
        SetAnimation ("Walk", true);

        if (Input.GetKeyDown("space"))
        {
            SetAnimation ("Walk-Jump", true);
            jumping = true;
        }
    } 
    else if (xDir < 0)
    {
        goalRotation = Quaternion.Euler (0, 180, 0);
        SetAnimation ("Walk", true);

        if (Input.GetKeyDown("space"))
        {
            SetAnimation ("Walk-Jump", true);
            jumping = true;
        }
    }
    else
    {
        SetAnimation ("Idle", true);

        if (Input.GetKeyDown("space"))
        {
            SetAnimation ("Idle-Jump", true);
            jumping = true;
        }
    }

    graphics.localRotation = Quaternion.Lerp (graphics.localRotation, goalRotation, rotateSpeed * Time.deltaTime);
}
0
votes

Change GetKeyDown to just GetKey.

As stated in the Unity input documentation here , GetKeyDown fires once during the frame that the key is pressed. GetKey will continue to fire as long as the button is held down.