neoMetalero
neoMetalero

Reputation: 68

Using Yield to make a function wait until something is true Unity C#

I'm trying to use Yield so my functions wait to spawn more enemies in scene if the max amount has been reached. But now the functions skips all this while cycle in its entirety. I have never use yield so maybe I'm understanding wrong what it does while reading the documentation. Also maybe there is a better way to do it.

while ( i < clonesASpawnear.Length)
    {          

        if (j <= endList)
        {      
                if (clonesASpawnear[i] == null)
                {

                    if (sPCurrent == sPMax)
                    {
                        sPCurrent = 0;
                    }                   

                yield return new WaitUntil(() => aliveEnemies < maxAmmoutOfEnemiesOnStage);

                clonesASpawnear[i] = Instantiate(enemyTypeList[j], spawnPoints[sPCurrent].transform.position, Quaternion.Euler(0, 0, 0)) as GameObject;
                    clonesASpawnear[i].SetActive(true);
                    clonesASpawnear[i].GetComponent<EnemyMovement_DCH>().player = Target;
                    aliveEnemies += 1;

                    clonesASpawnear[i].GetComponent<EnemyDamageHandler_DCH>().SpawnerEnemies = this;
                    j++;
                    i++;
                    sPCurrent++;


                }
            }               

        else
        {
            j = startList;
        }            



    }
}

Edited as requested: here is the update where the function is called

 void Update()
{
    if (pdh.playerIsDead == false && roundOver==false)
    {

        playerAliveTime += Time.deltaTime;
    }



    if (waveNumer <= 3 )
    {



        timeForNextSpawn -= Time.deltaTime;
        if (timeForNextSpawn <= 0 && aliveEnemies == 0)
        {


            nextWaveTextUI.text = nextWaveText;

            int waitT = (int)waitTimeForNewWave;
            StartCoroutine(delayXSeconds(waitT));


            timeForNextSpawn = waitTimeForNewWave;
            auxWaveThisRound--;

            waveNumer++;

            spawnEnemies();

        }
    }
    else
    {

        if(aliveEnemies == 0 && auxWaveThisRound <= 0)
        {
            clearedRoundTextUI.text = clearedRoundText;
            roundOver = true;



            StartCoroutine(waiterReset());


        }


    }

    accuracy = successfulProjectiles / projectileFired;


}

And the complete function where the above code is

IEnumerator spawnEnemies()
{

    int percentForWave=0;
    int percentForType=0;

    int TotalEnemies = (int)enemySpawnsThisRound;
    if (waveNumer == 1)
    {
        Debug.Log("Entro al wave 1");
        percentForWave = 20;
        percentForType = 20;
        startList = 0;

    }
    if (waveNumer == 2)
    {
        Debug.Log("Entro al wave 2");
        percentForWave = 70;
        percentForType = 70;
        startList = endList;

    }
    if (waveNumer == 3)
    {
        Debug.Log("Entro al wave 3");
        percentForWave = 10;
        percentForType = 10;
        startList = endList;
    }


    int enemiesThisWave = Decimal.ToInt32(Math.Round(TotalEnemies * ((decimal)percentForWave / 100), 1));
    int enemiesForType = Decimal.ToInt32(Math.Round(lenghtList * ((decimal)percentForType / 100), 1));

    endList = enemiesForType + startList;

    clonesASpawnear = new GameObject[enemiesThisWave];
    int i = 0;
    int j = startList;



    while ( i < clonesASpawnear.Length)
    {



        if (j <= endList)
        {
                if (clonesASpawnear[i] == null)
                {

                    if (sPCurrent == sPMax)
                    {
                        sPCurrent = 0;
                    }
                yield return new WaitUntil(() => aliveEnemies < maxAmmoutOfEnemiesOnStage);

                clonesASpawnear[i] = Instantiate(enemyTypeList[j], spawnPoints[sPCurrent].transform.position, Quaternion.Euler(0, 0, 0)) as GameObject;
                    clonesASpawnear[i].SetActive(true);//lo activo
                    clonesASpawnear[i].GetComponent<EnemyMovement_DCH>().player = Target;
                    aliveEnemies += 1;

                    clonesASpawnear[i].GetComponent<EnemyDamageHandler_DCH>().SpawnerEnemies = this;
                    j++;
                    i++;
                    sPCurrent++;


                }
            }

        else
        {
            j = startList;
        }


    }

}

Upvotes: 0

Views: 1891

Answers (1)

Asyranok
Asyranok

Reputation: 985

Do not use a while loop. Instead, use "Update()".

void Update() {

    if (aliveEnemies < maxAmmoutOfEnemiesOnStage && j <= endList)
    {      
            if (clonesASpawnear[i] == null)
            {

                if (sPCurrent == sPMax)
                {
                    sPCurrent = 0;
                }                   

            clonesASpawnear[i] = Instantiate(enemyTypeList[j], spawnPoints[sPCurrent].transform.position, Quaternion.Euler(0, 0, 0)) as GameObject;
                clonesASpawnear[i].SetActive(true);
                clonesASpawnear[i].GetComponent<EnemyMovement_DCH>().player = Target;
                aliveEnemies += 1;

                clonesASpawnear[i].GetComponent<EnemyDamageHandler_DCH>().SpawnerEnemies = this;
                j++;
                i++;
                sPCurrent++;


            }
        }               

    else
    {
        j = startList;
    }   

}

This is the idea of the Update frame. Logic in here is hit every frame. It will only continue if the number of enemies is below the max. This method MUST go into a class that extends MonoBehaviour, or else it will not be invoked. Given the intended logic, it makes sense that this would be attached to some master "game monitoring" GameObject that is managing the meta of the game along with win states etc.

EDIT (After more content): Heres one problem "spawnEnemies();". That is an IEnumerator, but you don't use "StartCoroutine(spawnEnemies())". So the method will literally not execute. There will be no errors, but nothing in the method will occur.

Upvotes: 1

Related Questions