协程是一个有多个返回点的函数。一般来说一个函数只有一个返回点,函数的调用者调用一次后,函数的生命周期就结束了。而对于协程来说,其生命周期由调用者来决定,可以通过返回值来决定如何进行一次调用以及如何结束调用。
由于协程返回的是一系列的值,每一个yield return对应一次返回。用迭代器作为返回类型是比较好的选择,可以简单的认为每一个yield return对于了迭代器中的一个元素。
Unity的C#代码中一个协程的返回值通常是IEnumerator类型,IEnumerator 接口有两个方法,分别是 Current 和 MoveNext。我们可以简单的认为:协程就是一个返回迭代器的函数,一开始迭代器的Current指向函数的开头,每执行一次MoveNext,Current就指向下一个yield return 返回的值。
一个最基本的协程使用方式就是
以上就是协程的基础知识。
协程在使用过程中,通常包含三个物体。
1.包含对应协程方法的物体(协程与MonoBehavior同级,是另一段脚本逻辑,隐藏物体也可以照样开始协程,但是销毁就不可以了)
2.调用协程载体(StartCoroutine脚本所挂载的游戏对象被隐藏了,协程将无法调用)
3.业务逻辑脚本,控制调用协程载体调用指定协程。
这一下就能分成三种结构,又有以下多种情况。
一。前面1和2组合,在业务脚本中获得一个引用,直接调用,但是如何协程中有逻辑隐藏了调用协程载体, 协程将直接停止,无法继续向下执行,更无法重新开启。相反,如果游戏协程已经开启,删除包含协程物体,调用协程载体没事,协程也会执行完,只不过无法重新开启此段协程。
二。前面3和2结合(和1结合也太low了,不会有人想这么干的吧)同样,调用协程载体没了,全没了,协程直接停止,无法向下运行,而业务脚本删除,协程也能保证执行完,只不过无法再次启动。
综上,强烈建议在项目开发中分成三个模块分离。保证协程的安全性和完整性。
测试脚本。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class test2 : MonoBehaviour
{
private testCor to;
private IEnumerator testEnum;
// Update is called once per frame
private void Awake()
{
to = GameObject.Find("协程脚本").GetComponent<testCor>();
testEnum = to.TestEnum();
}
void Update()
{
if(Input.GetKeyDown(KeyCode.Q))
{
if(to!=null)
CorGO.sharedInstance.StartCoroutine(testEnum);
else
{
Debug.LogError("go == null");
}
}
if(Input.GetKeyDown(KeyCode.Space))
{
CorGO.sharedInstance.StopCoroutine(testEnum);
}
}
}
using System.Collections;
using UnityEngine;
public class testCor:MonoBehaviour
{
public IEnumerator TestEnum()
{
yield return new WaitForSeconds(1f);
Debug.LogError("ice");
yield return new WaitForSeconds(1f);
Debug.LogError("icecold");
yield return new WaitForSeconds(5f);
Debug.LogError("icecoldless");
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
CorGO.sharedInstance.StartCoroutine(TestEnum());
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CorGO : MonoBehaviour
{
public static CorGO sharedInstance;
private void Awake()
{
sharedInstance = this;
}
}
test2 是业务
corgo是载体
testccor是协程脚本
在这三种物体中,业务按需求判断是否需要挂载游戏物体,载体必须挂载游戏物体,协程脚本可以不用挂载游戏物体,协程脚本分为短期协程和常驻协程,经常使用的建议保留不建议用完就撤,可以直接挂载到游戏GameLoop这种跟Root不销毁对象下,非常驻的用完一次就没了,也不需要什么协程池管理。
另外一个
协程计时回调。