Coroutine is not running code correctly the second time it is called

Viewed 98

I'm still learning to code so hopefully this is simple to resolve. I am trying to make a turn based RPG and I have run into a problem with my coroutines.

I use these to move the characters and it works the first time around (turn 1), regardless if I choose attack 1 or attack 2. However, when the player has exhausted his teams turns, the enemy attacks and then its the players turn again.

When I try to use an attack at this point the character runs in place forever. Not sure what the problem is but it's clear that the coroutine runs until it hits the first while loop because it is just after the running animation trigger animator.SetBool("Run", true).

The first coroutine is for the basic attack and the second is for special attacks. The enemyPos stores the Vector3 of the enemys location and it comes from another script.

I was researching coroutines but found many conflicting info. For example, that coroutines can't run at the same time, however it is a turn based game and it will only run once per turn per char (the same script is on all chars) so I not sure what the problem is.

I am writing in C# for Unity.

Sorry for novel haha and cheers for your help.

 IEnumerator Movement()
    {
        if (moving)
        {

            if (isAttacking == true)
            {
                animator.SetBool("Run", true); //Begin run

                if (base_Char.ranged == false)
                {
                    
                    while (transform.position != enemyPos)
                    {
                        transform.position = Vector3.MoveTowards(transform.position, enemyPos, base_Char.speed * Time.deltaTime);

                        yield return null;
                    }

                    animator.SetBool("Run", false); //End run when location reached

                }

                else if (base_Char.ranged == true)
                {
                    Vector3 stepForward = new Vector3(transform.position.x + 2f, transform.position.y, transform.position.z); //For ranged attackers

                    while (transform.position != stepForward)
                    {
                        transform.position = Vector3.MoveTowards(transform.position, stepForward, base_Char.speed / 2 * Time.deltaTime);
                        yield return null;
                    }

                    animator.SetBool("Run", false);

                }

                //TEMPORARY to check if their is an animator on enetity
                if (GetComponent<Animator>() != null)
                {
                    animator.SetTrigger("BasicATK"); //Enable Basic attack trigger
                }

                yield return new WaitForSeconds(1.5f);
                BasicAttack(enemyPos);


            }



            else if (isAttacking == false)
            {
                animator.SetBool("Run", true); //Begin run

                while (transform.position != startingPos)
                {
                    transform.position = Vector3.MoveTowards(transform.position, startingPos, base_Char.speed * 2 * Time.deltaTime);
                    yield return null;
                }

            }

            animator.SetBool("Run", false); 
            moving = false; //Stop Update, used when testing with Update()
            base_Char.turnOver = true;
            base_Char.RunTurnCheck();

        }

    }


IEnumerator MoveChar(string movement)
    {
        if (movement == "Enemy")
        {
            while (transform.position != enemyPos)
            {
                transform.position = Vector3.MoveTowards(transform.position, enemyPos, base_Char.speed * 1.5f * Time.deltaTime);

                yield return null;
            }

        }

        if (movement == "Middle")
        {
            Vector3 target = new Vector3(0, 2, transform.position.z);

            while (transform.position != target)
            {
                transform.position = Vector3.MoveTowards(transform.position, target, base_Char.speed * Time.deltaTime);

                yield return null;
            }

        }

        if (movement == "StepForward")
        {
            Vector3 target = new Vector3(transform.position.x + 1f, transform.position.y, transform.position.z);

            while (transform.position != target)
            {
                transform.position = Vector3.MoveTowards(transform.position, target, base_Char.speed * Time.deltaTime);

                yield return null;
                
            }

        }

        base_Char.turnOver = true;
        base_Char.RunTurnCheck();

        yield return new WaitForSeconds(2f);

        while (transform.position != base_Char.startingPos)
        {
            transform.position = Vector3.MoveTowards(transform.position, base_Char.charPos.transform.position, base_Char.speed * 2 * Time.deltaTime);

            yield return null;
        }
    }
1 Answers

I might need more information, for example what does the base_Char.RunTurnCheck(); func do? What does your update function look like?

However, my advice would be to make a state machine rather than run everything through a single class. You can make a state class, code all the specific behaviour there and just pass it into the state machine for it to execute, which would massively increase your extensibility.

Related