Friday, November 6, 2015

Yield bogeyman 2/2

This is second part of a blog, in which I am trying to explain yield keyword and its use in Unity. The first part is there.

In Unity we usually execute majority of the code every frame in Update() calls. However sometimes we need to do actions in defined interval (e.g. every second) or at some exact time after user starts the game level.

For that purpose we use something Unity calls coroutine. We already know that using yield keyword we could execute a method, return from it preserving its state between calls and continue the method execution later. A coroutine is using the yield keyword to do exactly the same - pause execution, return control to Unity and continue later where it was left.

For testing purposes let's define a coroutine with the endless while loop. Note that in Unity the coroutine needs to be started by using the StartCoroutine() method call:
void Start () 
{
 StartCoroutine(TestCoroutine());
}

void Update () 
{
 Debug.Log("[CoroutineTest]:[Update] Time: " + Time.deltaTime );
}


IEnumerator TestCoroutine()
{
 while (true)
 {
  yield return 1;
  Debug.Log("[CoroutineTest]:[TestCoroutine] Time: " + Time.deltaTime );
 }
}
After you will execute the code, you will notice from console logs that the Update() and Log() functions are called with the same frequency - i.e. the execution of the coroutine is resumed every frame. Using corountines that way might be useful in some cases because it allows easy dividing of standard methods to its parts called periodically every frame, but it is not what we want to achieve now: We want to call coroutine regularly at defined interval - one second in our case.

For that purpose Unity has the special class called WaitForSecondsUsing that class (It can only be used with a yield statement in coroutine.) we are able to suspend a coroutine for the given amount of seconds. The modified code is below:
void Start () 
{
 StartCoroutine(TestCoroutine());
}

void Update () 
{
 Debug.Log("[CoroutineTest]:[Update] Time: " + Time.deltaTime );
}


IEnumerator TestCoroutine()
{
 while (true)
 {
  yield return new WaitForSeconds(1);
  Debug.Log("[CoroutineTest]:[TestCoroutine] Time: " + Time.time );
 }
}
In console logs you will see that the TestCoroutine() method is called approximatelly every second:
...
[CoroutineTest]:[Update] Time: 0.005466057
[CoroutineTest]:[Update] Time: 0.00672265
[CoroutineTest]:[TestCoroutine] Time: 2.003362
[CoroutineTest]:[Update] Time: 0.004957338
[CoroutineTest]:[Update] Time: 0.005276212
...
[CoroutineTest]:[TestCoroutine] Time: 3.006917
...

No comments:

Post a Comment