Unity协程实用技巧
基本使用
//type 1
IEnumerator CoroFunc1()
{
yield return null;
}
//type 2 yield return type is limited to string
IEnumerator<string> CoroFunc2()
{
yield return "hello";
}
//type 3 with param
IEnumerator<string> CoroFunc3(string str)
{
yield return "hello" + str;
}
//type 4 return IEnumerable: not necessary.
IEnumberable CoroFunc4(int i)
{
yield return null;
}
创建并开始协程:
//type 1 use anywhere inside a monobehaviour class
Coroutine coro = StartCoroutine(CoroFunc1());
//type 2 use inside a coroutine, unity automatically create a Coroutine, and call it next frame.
yield return CoroFunc1();
//type 3 just don't use it, very slow
Coroutine coro = StartCoroutine("CoroFunc4", 1);
停止协程:
StopCoroutine(coro);
内置的YieldInstruction
除了常用的WaitForSeconds
,WaitForEndOfFrame
等,以下同样继承自YieldInstruction
的子类也有其便捷之处:
- WaitUntil
- WaitWhile
bool finishCondition = false;
yield return new WaitUntil(() => finishCondition)
//go on when finishCondition is true
可返回值的协程
有时会有这种需求:等待协程结束后,获取到yield return
的结果。
//pseudocode
var retCode = yield return new XXX();
Print(retCode);
除了网络上给出的较早的实现方式外,现在还可以利用CustomYieldInstruction
来实现。
public class CoroutineWithData : CustomYieldInstruction
{
public int retCode { get; private set; }
private bool _finished = false;
public void onFinished(bool isSucc)
{
_finished = true;
retCode = isSucc ? 0 : -1;
}
//must override this
public override bool keepWaiting
{
get
{
return !_finished;
}
}
}
//how to use:
public class main : MonoBehaviour {
private IEnumerator Start()
{
CoroutineWithData coro = new CoroutineWithData();
yield return coro;
Debug.Log("retcode:" + coro.retCode);
}
//click btn to continue coro
public void btnClickHandler()
{
coro.onFinished(true);
}
}
嵌套协程
协程的嵌套使用不仅是为了更明了地组织逻辑代码,而且可以实现协程同步:
- 同步、阻塞式(最基本用法)
IEnumerator A()
{
yield return StartCoroutine(B());
//wait for B() finishes
}
同时进行
IEnumerator A() { StartCoroutine(B()); //execute at the same time }
异步,阻塞式 ```cs IEnumerator A() { Coroutine sub = StartCoroutine(B());
//do sth at the same time
yield return sub;
//wait for B() finishes }
IEnumerator AA() { Coroutine sub1 = StartCoroutine(B()); Coroutine sub2 = StartCoroutine(B());
//do sth at the same time
yield return sub1;
yield return sub2;
//wait for all finishes
}
## 多态协程
```cs
//parent class:
protected virtual IEnumberator DoSomething()
{
yield return null;
}
//child class
protected override IEnumberator DoSomething()
{
//you can call base like this:
yield return StartCoroutine(base.DoSomething();
//do something
}
可处理异常的协程
http://twistedoakstudios.com/blog/Post83_coroutines-more-than-you-want-to-know