Home c# Why are coroutines in Unity?

Why are coroutines in Unity?

Author

Date

Category

Why coroutines in Unity?
After all, as far as I understand, they allow you to perform some actions in parallel, during the main work of the program. The loop of waiting for the connection to twist there.
In Unity, in each script, we can add Update, FixedUpdate, LateUpdate.
At the same time, we have such a great method as InvokeRepeating, which can also

run something of your own in parallel, with the required frequency, and more than once in each script.

While there can be as many scripts as you like.

Is there any real need for coroutines in Unity? Maybe they are better in terms of performance? Or can it be applied more precisely?


Answer 1, authority 100%

First, I’ll write right away that it is not entirely correct to compare coroutine with Update, FixedUpdate, LateUpdate and InvokeRepeating. For it can only be performed once. For example

void Start () {
  Debug.Log ("Start game");
  StartCoroutine (wait ());
}
IEnumerator wait () {
  yield return new WaitForSeconds (3f);
  Debug.Log ("Coroutine is work");
}

will print Start game and after 3 seconds Coroutine is work . Everything. No repeated calls.


Next.

It differs from all of the above methods at least in the presence of the yield keyword. When a yield return statement is encountered in an iterator method (which is a coroutine), the expression is returned and the current position in the code is saved. Execution will continue from this location on the next call to the iterator function.

Example

void Start () {
  StartCoroutine (Test (FinalAction));
}
IEnumerator Test (Action act) {
for (int i = 0; i & lt; 5; i ++) {
    Debug.Log ("Test" + i);
    yield return new WaitForSeconds (1.5f);
    Debug.Log ("Test" + i + i);
  }
}

“Test0” will be displayed, and after 1.5 seconds “Test00”, “Test1” (since the program continued execution from the moment it stopped and then continued the cycle again) … then “Test11”, “Test2 “etc.

Thus, the coroutine allows you to interrupt calculations, give resources to the main thread, and then resume the next part of the calculations.


Another example: we need to instantiate 10.000 objects. Serves 10-100 or just in a cycle, it doesn’t matter. If we stick this in the Update method, then until the loop is done updating the screen, the application “hangs” all this time. The user has a “bomb”. That is, coroutine can be used for long-term operations that can be “smeared” across frames. Moreover (as written above) you can call approximately the following sequence of actions:

// loop counter
Debug.Log ("We instantiate objects and store them in an array");
yield return new WaitForSeconds (1);
Debug.Log ("do additional work with this array");
yield return new WaitForSeconds (1);
Debug.Log ("Some more work");
yield return new WaitForSeconds (1);

another bullet example:

void Start () {
   StartCoroutine ("FireThriceAndWait");
 }
 IEnumerator FireThriceAndWait () {
   while (true) {
     fire ();
     yield return new WaitForSeconds (0.5f);
     fire ();
     yield return new WaitForSeconds (0.5f);
     fire ();
     yield return new WaitForSeconds (5f);
   }
 }
 void fire () {
Instantiate (enemy_bullet, this.transform.position, Quaternion.LookRotation (target.transform.position- this.transform.position));
 }

InvokeRepeating will not allow such work in principle.

Another example. We want something to happen before and after the execution of actions, for example, logging messages is something done or not. How do I do this in InvokeRepeating or Update? To hang up any flags, something was done or not, went into the method or not? Why, if you can do it in the coroutine

void Start () {
  StartCoroutine (Test (StartAction, FinalAction));
}
IEnumerator Test (Action actBefore, Action actAfter) {
  actBefore ();
  for (int i = 0; i & lt; 5; i ++) {
    Debug.Log ("Test" + i);
    yield return new WaitForSeconds (1.5f);
    Debug.Log ("Test" + i + i);
  }
  actAfter ();
}
void StartAction () {
  Debug.Log ("I'm a start action");
}
void FinalAction () {
  Debug.Log ("I'm a final action");
}

Well, another example .. let’s say we want to make the sprite flash (decrease transparency, increase) with an interval of 0.5 sec. Let’s put the methods in Update – the main thread will hang. For InvokeRepeating, you will have to set different flags and additional functions – whether the required method was called or not, if yes, then repeat another method, if not, then the first one … The coroutine solves it like this

IEnumerator Test () {
  while (true) {
    var color = obj.GetComponent & lt; Renderer & gt; (). material.color;
    for (float i = 1; i & gt; = 0; i- = 0.1f) {
      color.a = i;
      obj.GetComponent & lt; Renderer & gt; (). material.color = color;
      yield return null;
    }
    yield return new WaitForSeconds (0.5f);
for (float i = 0; i & lt; 1; i + = 0.1f) {
      color.a = i;
      obj.GetComponent & lt; Renderer & gt; (). material.color = color;
      yield return null;
    }
    yield return new WaitForSeconds (0.5f);
  }
}

Loops can be put into separate methods – but not the essence. The fact is that if you run it, the coroutine will run in parallel without freezing and complex manipulations.


And the coroutine can also wait for actions from ForFixedUpdate, i.e. aborts execution until the frame in which the physics is updated (called by WaitForFixedUpdate) or the end of the frame (WaitForEndOfFrame). What can be useful to do and for the same InvokreRepeating you will have to sculpt something for this.


As a result . As I described above: coroutine can be used for lengthy operations that can be “smeared” over frames from which the main thread will not hang. For some separate microprogram that will run in parallel (an example with a flashing sprite, or start a character to wander in one direction and the other “tween”), which is difficult to fix due to the difference in actions.

And do not forget that in the same Update instructions occur sequentially, which means a dozen methods with loops, in which certain actions, set one after another, will be executed sequentially and longer than coroutines, and the game itself may depend on this: the player jumped up 10 times and then shot 10 times or jumped and shot 10 times – the difference.

I hope I haven’t confused you)

Programmers, Start Your Engines!

Why spend time searching for the correct question and then entering your answer when you can find it in a second? That's what CompuTicket is all about! Here you'll find thousands of questions and answers from hundreds of computer languages.

Recent questions