One of the scripts on my scene involves creating a grid of cubes. The process does take a fair amount of time and I've been trying to implement it without causing Unity to become unresponsive.
The code at present - works to effect - you can watch as the grid is generated. However, the other scripts in the scene are doing their tasks at the same time and is causing exceptions (they're accessing tiles on the grid which are not yet created).
The script below is the only script that has an 'Awake' function - the other scripts are executing 'Update' and 'OnGUI' before the first script has finished its awake.
GridGenerator.cs
public GameObject[,] tiles = new GameObject[Constants.BOARD_WIDTH, Constants.BOARD_HEIGHT];
// Run a double loop to create each tile.
void Awake ()
{
StartCoroutine(doSetup());
}
IEnumerator doSetup()
{
yield return StartCoroutine (loadLevel());
DoOtherStuff();
}
IEnumerator loadLevel()
{
for (int i = 0; i < Constants.BOARD_WIDTH; i++)
{
for (int j = 0; j < Constants.BOARD_HEIGHT; j++)
{
tiles[i,j] = newTile();
yield return(0);
}
}
}
How would I make the doOtherStuff() method wait until the co-routine is finished?
I've tried a boolean toggle (which froze unity) I've tried using lock (which didn't work)
Or is there a more efficient way of doing this?
EDIT: The code successfully completes OtherStuff() after the the grid is generated. Apart of the doOtherStuff() is to pass a reference of the grid to a separate class. The separate class is throwing exceptions when trying to access the grid in the Update method. Which suggests, the update method is being called before the Awake in the GridGenerator.cs is completed.
Coroutines can be used to execute a piece of code across multiple frames. They can also be used to keep executing a section of code until you tell it to stop. A coroutine contains a yield instruction that will wait a certain amount of time you tell it to.
So while we all know that coroutines do not run simultaneously, they do run interleaved.
If you want to wait for one coroutine till it finishes, you can put yield return Coroutine1(); at first line in the body Coroutine2 and put the rest of the code after that, this way the Coroutine2 will wait for Coroutine1 till its done, then it will proceed with the rest of the code.
The easiest way would be to kick off your coroutine within another coroutine, so that you can yield to it:
void Awake ()
{
StartCoroutine(doSetup());
}
IEnumerator doSetup ()
{
yield return StartCoroutine(createGrid()); // will yield until createGrid is finished
doOtherStuff();
}
IEnumerator createGrid()
{
for (int i = 0; i < Constants.BOARD_WIDTH; i++)
{
for (int j = 0; j < Constants.BOARD_HEIGHT; j++)
{
// Instantiate a new tile
yield return(0);
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With