在外面使用协程的时候
/// <summary>
/// 当在IEnumerator 函数中使用yild return 语句中 每次使用就会增加迭代器里面的元素 Add
/// </summary>
/// <returns></returns>
IEnumerator WaitAndPrint()
{
Debug.Log(11);
yield return null; //每一帧调用
Debug.Log(2);
yield return 11;///每一帧调用
Debug.Log(333);
yield return new WaitForSeconds(1);
yield break;
Debug.Log(99);
yield return 999;
}
总要生命一个返回 IEnumerator 的函数 里面写 yield return之类的语句
这个就是迭代器 他是c#的特别NB的一个功能 只要继承了IEnumerable 的接口
就实现了 foreach 去遍历这个类 输出接口是根据GetEnumerator 返回的类型来决定
为了简化 所有我们使用 了yield
在函数中使用yield 就相当于在迭代器里面添加了 一个元素
看看代码
void Start()
{
// StartCoroutine("WaitAndPrint");
IEnumerator enumerator = WaitAndPrint();
while (enumerator.MoveNext())
{
Debug.Log(enumerator.Current);
}
StartCoroutine("CaculateResult",10);
NonMonoClass.Instance.Test();
}
外面已经初步了解了
核心
协程在每次执行时都会新建一个(伪)新线程来执行,而不会影响主线程的执行情况。
协程并不会在Unity中开辟新的线程来执行,其执行仍然发生在主线程中
分别是StartCoroutine(/这里直接调用方法,添加参数/),另一种是StartCoroutine(/这里填写”字符串的方法名字”,方法参数/)。第一种方法的优势在于可以调用多个参数的方法,后一种方法只能调用不含参数或只包含一个参数的协程方法。但是第一种方法不能通过StopCoroutine(/这里填写”字符串的方法名”/)来结束协程,只能通过StopAllCoroutines来结束。后一种则可以通过StopCoroutine来结束对正在执行的协程的调用。
yield return null; // 下一帧再执行后续代码
yield return 0; //下一帧再执行后续代码
yield return 6;//(任意数字) 下一帧再执行后续代码
yield break; //直接结束该协程的后续操作
yield return asyncOperation;//等异步操作结束后再执行后续代码
yield return StartCoroution(/*某个协程*/);//等待某个协程执行完毕后再执行后续代码
yield return WWW();//等待WWW操作完成后再执行后续代码
yield return new WaitForEndOfFrame();//等待帧结束,等待直到所有的摄像机和GUI被渲染完成后,在该帧显示在屏幕之前执行
yield return new WaitForSeconds(0.3f);//等待0.3秒,一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后(这里的时间会受到Time.timeScale的影响);
yield return new WaitForSecondsRealtime(0.3f);//等待0.3秒,一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后(这里的时间不受到Time.timeScale的影响);
yield return WaitForFixedUpdate();//等待下一次FixedUpdate开始时再执行后续代码
yield return new WaitUntil()//将协同执行直到 当输入的参数(或者委托)为true的时候....如:yield return new WaitUntil(() => frame >= 10);
yield return new WaitWhile()//将协同执行直到 当输入的参数(或者委托)为false的时候.... 如:yield return new WaitWhile(() => f
当某一个脚本中的协程在执行过程中,
如果我们将该脚本的enable设置为false
,协程不会停止。只有将挂载该脚本的物体设置为
SetActive(false)
时才会停止。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IEun : MonoBehaviour
{
private void Awake()
{
Debug.Log("点我一下试试");
}
// Start is called before the first frame update
void Start()
{
// StartCoroutine("WaitAndPrint");
IEnumerator enumerator = WaitAndPrint();
while (enumerator.MoveNext())
{
Debug.Log(enumerator.Current);
}
// StartCoroutine("CaculateResult",10);
NonMonoClass.Instance.Test();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
StopCoroutine("CaculateResult");
Debug.Log("我不跑了");
}
if (Input.GetKeyDown(KeyCode.A))
{
transform.GetComponent<IEun>().enabled = false;
}
}
IEnumerator CaculateResult(int n)
{
// Debug.LogError(n);
for (int i = 0; i < 1000; i++)
{
Debug.Log("我在跑");
//内部循环计算
//在这里的yield会让改内部循环计算每帧执行一次,而不会等待10000次循环结束后再跳出
yield return null;
}
Debug.Log("跑完了");
yield return null;
}
/// <summary>
/// 当在IEnumerator 函数中使用yild return 语句中 每次使用就会增加迭代器里面的元素 Add
/// </summary>
/// <returns></returns>
IEnumerator WaitAndPrint()
{
Debug.Log(11);
yield return null; //每一帧调用
Debug.Log(2);
yield return 11;///每一帧调用
Debug.Log(333);
yield return new WaitForSeconds(1);
yield break;
Debug.Log(99);
yield return 999;
}
private void OnMouseDown()
{
StartCoroutine("CaculateResult", 10);
}
}
public class NonMonoClass
{
public MonoBehaviour mono;
private static NonMonoClass _instance;
public static NonMonoClass Instance
{
get
{
if (_instance == null)
{
_instance = new NonMonoClass();
}
return _instance;
}
}
public void Test()
{
mono.StartCoroutine(testFunction());
}
IEnumerator testFunction()
{
yield return new WaitForSeconds(3f);
Debug.Log("Test!");
}
}