Search code examples
c#unity-game-enginewait

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.


Solution

  • 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;
    }