看了siki老师的视频,加深了对协程的理解。
如果是普通方法,则按照下图方式执行。
比如:
void Start ()
{
print(1);
Hello();
print(2);
}
void Hello()
{
print("hello");
print("hello");
}
上述代码输出的结果是1,hello,hello,2
而如果我们用协程的话,比如:
void Start ()
{
print(1);
//这里开启协程
StartCoroutine(Hello());
print(2);
}
IEnumerator Hello()
{
print("hello");
print("hello");
yield return null;
}
那么输出的结果可能是1,hello,hello,2
或者1,2,hello,hello
或者1,hello,2,hello
因为协程的执行原理是这样的:
类似并发执行的样子,在我们例子中Start()和Hello()语句的具体执行顺序要看cpu的调度情况,所以是不确定的。
另外,需要特别注意的一点是:
我们开启协程用StartCoroutine()方法,可以这样写:
StartCoroutine(Hello());
或者这样StartCoroutine(“Hello”),
如果我们用字符串作为方法名来开启协程,那么必须以字符串来终止协程——
StopCoroutine(“Hello”),否则无法停止协程。
那么,如果我们这样写呢?
StartCoroutine(Hello());
StopCoroutine(Hello());
经测试,依然无法停止协程。
不过,这样写也可以停止协程:
“`
private IEnumerator ie;
void Start ()
{
ie = Test();
}
void Update ()
{
if (Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine("Test");
}
if (Input.GetKeyDown(KeyCode.S))
{
StopCoroutine(ie);
}
}
IEnumerator Test()
{
while (true)
{
print("test");
yield return null;
}
}
只有以上两种组合方式能正确的停止协程。
但是,还有一种简单粗暴的方式,就是无论你使用何种语句开始协程,
StopAllCoroutines()可以直接停止所有协程。
下面附上官方对协程的解释:
“在Unity3D中,使用MonoBehaviour.StartCoroutine方法即可开启一个协同程序,也就是说该方法必须在MonoBehaviour或继承于MonoBehaviour的类中调用。
在Unity3D中,使用StartCoroutine(string methodName)和StartCoroutine(IEnumerator
routine)都可以开启一个线程。区别在于使用字符串作为参数可以开启线程并在线程结束前终止线程,相反使用IEnumerator
作为参数只能等待线程的结束而不能随时终止(除非使用StopAllCoroutines()方法);另外使用字符串作为参数时,开启线程时最多只能传递一个参数,并且性能消耗会更大一点,而使用IEnumerator
作为参数则没有这个限制。
在Unity3D中,使用StopCoroutine(string methodName)来终止一个协同程序,使用StopAllCoroutines()来终止所有可以终止的协同程序,但这两个方法都只能终止该MonoBehaviour中的协同程序。
还有一种方法可以终止协同程序,即将协同程序所在gameobject的active属性设置为false,当再次设置active为ture时,协同程序并不会再开启;如是将协同程序所在脚本的enabled设置为false则不会生效。这是因为协同程序被开启后作为一个线程在运行,而MonoBehaviour也是一个线程,他们成为互不干扰的模块,除非代码中用调用,他们共同作用于同一个对象,只有当对象不可见才能同时终止这两个线程。然而,为了管理我们额外开启的线程,Unity3D将协同程序的调用放在了MonoBehaviour中,这样我们在编程时就可以方便的调用指定脚本中的协同程序,而不是无法去管理,特别是对于只根据方法名来判断线程的方式在多人开发中很容易出错,这样的设计保证了对象、脚本的条理化管理,并防止了重名。”