1:
Yes, you can start a coroutine inside Update, and in fact this is a perfectly valid form of control flow (for example, if you want to perform some coroutined action over time after recieving a key-press). So long as you use ‘StartCoroutine(nameOfCoroutine(paramaters));’, you should be fine.
2:
The yield statement can be used like any other line of code, and as such can be controlled by conditionals and loops just like anything else. There is aboslutely no reason why you can’t do this.
3: If you want to yield for a function in a different script, first make sure you have a reference to that object (obviously!), and then you can call it just like any other public function, so long as you couch it inside the StartCoroutine method call. So:
yield return new StartCoroutine(otherScript.SomeCoroutine());
will work perfectly.
4: Unfortunately, it is not possible to return data from a coroutine (because of the way the scheduler works internally). If you need to read from data that is modified inside the coroutine, you’ll have to just refer to members variables (rather than scope variables), since these will exist outside the scope of the coroutine.
int incrementMeOverTime = 0;
IEnumerator IncreaseTimer(float tickTime, int countUpTo)
{
do {
yield return new WaitForSeconds(tickTime);
incrementMeOverTime++;
} while (countUpTo-- > 0);
}
Outside this, you can read off ‘incrementMeOverTime’ to find the state of the coroutine, although I admit that this doesn’t really feel like an ‘elegant’ solution.
The best way to get around this would be to declare a class to hold your output data, and then pass a reference to that class into the coroutine. Then, when the corutine is finished, you can read the data contained in that class.
class CoroutineInfo
{
public int incrementMeOverTime = 0;
}
// in the function
CoroutineInfo myInfo = new CoroutineInfo;
StartCoroutine(IncreaseTimer(myInfo));
Debug.Log("The timer got to: " + myInfo.incrementMeOverTime);
5: Every time you use the ‘yield’ statement, the coroutine will pause execution for at least one frame. If you use ‘yield return null’, it will still pause for a frame- which allows you to use it a little like a temporary ‘Update’ function (that only gets executed up until the coroutine finishes). If you use something like ‘WaitForSeconds’, of course, execution will wait for longer than just one frame.
(Code examples are in C# because the syntax for coroutines is clearer in that language, and makes it more obvious exactly what is going on. I have had any number of questions here about JS couroutine, mostly stemming from justified confusion about exactly how they work. My apologies if it’s not your preferred language)
Used correctly, Coroutines can almost completely supplant the Update loop. They tend to be more efficient, because if you code them right they will only be called when they actually need to do something, not just every frame like Update, and it’s extremely easy to insert timing information into them (where you would have to keep and increment a member variable if you were to do that kind of thing in Update). Lately I’ve been reimplementing a lot of my older code to use them more extensively, because they make control flow more generally intuitive.
While it takes a little bit of practice to get your head around exactly what can and cannot be done with them (for example, you can’t pass references to value types into a coroutine- however, you can pass a reference to a reference type), coroutines are a very powerful tool in your shed, and you would do well to familiarise yourself with them.