Skuffd
Skuffd

Reputation: 363

How to delay movement in unity while animation plays

I am having difficulty delaying the movement of my character in Unity 2018.4, I suspect this is more of just a problem with my code as apposed to unity.

Edit: I want to be able to hold down the right arrow key, have the character not move for 415ms, then be able to move for 580ms, after which he cannot move for 350ms (to let the animation finish playing)

I tried using countdown in a IE numerator to wait and then call my movement function but this results in my character not moving after the animation has played.

//What makes the character move, works fine if executed on its own in update
private void ExecuteMovement(float dir)
    {
        currentPosition = transform.position;
        currentPosition.x += dir * Time.deltaTime * speed;
        transform.position = currentPosition;
    }

//Trying to use waitforseconds to delay the execution while the animation plays
private IEnumerator Movement(float dir)
    {
        yield return new WaitForSeconds(0.5f);

        ExecuteMovement(dir);
    }

void Update()
    {
        if (0 > Input.GetAxis("Horizontal"))
        {
            //This is to flip image
            transform.eulerAngles = new Vector3(0, 180, 0);

            //starts animation
            animator.SetBool("isSkipping", true);

            //calls the movement function with the direction to move in
            Movement(Input.GetAxis("Horizontal"));

        }

        else if (0 < Input.GetAxis("Horizontal"))
        {
            //This is to flip image
            transform.eulerAngles = new Vector3(0, 0, 0);

            //starts animation
            animator.SetBool("isSkipping", true);

            //calls the movement function with the direction to move in
            Movement(Input.GetAxis("Horizontal"));

        }
    }

I'm happy to try any alternatives to delaying movement of the character. The animation shows the character charging up to jump and then jumps. I want to only move while it is in the air which is approximately half a second into the animation.

Upvotes: 1

Views: 2245

Answers (3)

derHugo
derHugo

Reputation: 90659

You are trying to call your IEnumerator like a method.


Instead you have to start it as a Coroutine using StartCoroutine

StartCoroutine(Movement(Input.GetAxis("Horizontal")));

Saw your edit

I want to be able to hold down the right arrow key, have the character not move for 415ms, then be able to move for 580ms, after which he cannot move for 350ms (to let the animation finish playing)

until now so since you want a continues movement but still fully control the speed I would keep it in Update and use the coroutine only for controlling a flag. Coroutine is still way better to read/write and maintain. (Now it also allows direction switch midair .. not sure if you want this or not):

// control the ability to move with a simple flag
// instead of various states
public bool canMove;

// check if a jumping is already being animated/executed 
// -> disallow a new jumping animation until it is finished
private bool canJump = true;

private void Update()
{
    // avoid repeated API calls
    var input = Input.GetAxis("Horizontal");

    if (input < 0)
    {
        //This is to flip image
        transform.eulerAngles = new Vector3(0, 180, 0);

        if(canJump)
        {
            //starts the movement
            StartCoroutine(Jump());
        }
    }
    else if (input > 0)
    {
        //This is to flip image
        transform.eulerAngles = new Vector3(0, 0, 0);

        if(canJump)
        {
            //starts the movement
            StartCoroutine(Jump());
        }
    }

    // if can not move do nothing else
    if(!canMove) return;

    // execute the movement
    transform.position += Vector3.right * input * speed * Time.deltaTime;
}

private IEnumerator Jump()
{
    // disable jumping
    canJump = false;

    // disable move during animation
    canMove = false;

    //starts animation
    animator.SetBool("isSkipping", true);

    // not move for 415ms
    yield return new WaitForSeconds(0.415f);

    // enable move
    canMove = true;

    // be able to move for 580ms
    yield return new WaitForSeconds(0.580f);

    // disable move
    canMove = false;

    // cannot move for 350ms during end of animation
    yield return new WaitForSeconds(0.350f);

    // enable move again
    canMove = true;

    // re-enable jumping
    canJump = true;
}

Upvotes: 3

Skuffd
Skuffd

Reputation: 363

I found a rather crude way of making this work after heavily modifying Gray_Rhino's answer to this question. I set up 3 stages of my jump animation, when continually moving one direction a timer will check to see how far into the animation it is and decide whether or not to allow movement input. the timer resets after the animation is finished or the character is told to move in the other direction.

bool facingRight;
    int jumpPhase = 1;
    float timer = 0f;
    float dir;
    void Update()
    {
        if (jumpPhase != 3)
        {
            dir = Input.GetAxis("Horizontal");
        }

        if (0 > dir || (jumpPhase == 3 && facingRight == true))
        {
            timer += Time.deltaTime;

            if (facingRight != true)
            {
                transform.eulerAngles = new Vector3(0, 180, 0);
                jumpPhase = 1;
                timer = 0f;
                facingRight = true;
            }

            else if (jumpPhase == 1)
            {
                //starts animation
                animator.SetBool("isSkipping", true);

                if (timer >= 0.415f)
                {
                    jumpPhase = 2;
                }
            }

            else if (jumpPhase == 2)
            {
                ExecuteMovement(dir);

                if (timer >= 0.995f)
                {
                    jumpPhase = 3;
                }
            }

            if (jumpPhase == 3)
            {
                if (timer >= 1.5f)
                {
                    jumpPhase = 1;
                    timer = 0f;
                }
            }

        }

        else if (0 < dir || (jumpPhase == 3 && facingRight != true))
        {
            timer += Time.deltaTime;            

            if (facingRight == true)
            {                
                transform.eulerAngles = new Vector3(0, 0, 0);
                jumpPhase = 1;
                timer = 0f;
                facingRight = false;
            }

            else if (jumpPhase == 1)
            {
                //starts animation
                animator.SetBool("isSkipping", true);

                if (timer >= 0.415f)
                {
                    jumpPhase = 2;
                }
            }

            else if (jumpPhase == 2)
            {
                ExecuteMovement(dir);

                if (timer >= 0.995f)
                {
                    jumpPhase = 3;
                }
            }

            if (jumpPhase == 3)
            {
                if (timer >= 1.5f)
                {
                    jumpPhase = 1;
                    timer = 0f;
                }
            }

        }
    }

Upvotes: 0

Gray_Rhino
Gray_Rhino

Reputation: 1293

How about using timer in Update?

float timer = 0f;
void Update()
{
    var dir = Input.GetAxis("Horizontal");
    if (0 > dir)
    {
        //This is to flip image
        transform.eulerAngles = new Vector3(0, 180, 0);

        //starts animation
        animator.SetBool("isSkipping", true);

        //calls the movement function with the direction to move in
        timer +=Time.deltaTime;
        if(timer >= 0.5){
           ExecuteMovement(dir);
           timer -=0.5f;
        }
        //Movement(Input.GetAxis("Horizontal"));

    }

    else if (0 < dir)
    {
        //This is to flip image
        transform.eulerAngles = new Vector3(0, 0, 0);

        //starts animation
        animator.SetBool("isSkipping", true);

        //calls the movement function with the direction to move in
        timer +=Time.deltaTime;
        if(timer >= 0.5){
           ExecuteMovement(dir);
           timer -=0.5f;
        }
        //Movement(Input.GetAxis("Horizontal"));

    }
}

Upvotes: 2

Related Questions