协程 有人说在4.0以上的.net中已被弃用 用了新的方法替代 https://stackoverflow.com/questions/64258574/what-is-an-ienumerator-in-c-sharp-and-what-is-it-used-for-in-unity 说如果每次spawn时遵循斐波那契数列 这种update会很难写 先放着
StartCoroutine 用来启动协程 协程的执行可以在任何时候使用 yield 语句暂停。当使用 yield 语句时,协程会暂停执行并在下一帧自动恢复 StartCoroutine 方法在第一个 yield 返回时返回,但是您可以 yield 结果,它会等待协程完成执行。 不能保证协程以它们开始的相同顺序结束,即使它们在同一帧中完成。 任何类型的输出(包括 null)都会导致执行在稍后的帧上返回,除非协程停止或已完成。 StartCoroutine官方文档 https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html 第一个例子 使用了WaitForSeconds 时间不精确 跑到53分钟时 打印出了奇数时间
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
private IEnumerator coroutine;
void Start()
{
print("Starting " + Time.time);
coroutine = WaitAndPrint(2.0f);
StartCoroutine(coroutine);
print("Before WaitAndPrint Finishes " + Time.time);
}
private IEnumerator WaitAndPrint(float waitTime)
{
while (true)
{
print("Start协程" + Time.time);
yield return new WaitForSeconds(waitTime);
print("完成协程 " + Time.time);
}
}
}
结果是输出 Starting 0 Start协程0 Before WaitAndPrint Finishes0 完成协程 2.000603 Start协程2.000603 完成协程 4.001181 Start协程4.001181 …
第二个例子
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
IEnumerator Start()
{
print("Starting " + Time.time);
yield return StartCoroutine(WaitAndPrint(2.0f));
print("Done " + Time.time);
}
IEnumerator WaitAndPrint(float waitTime)
{
print("Start协程 " + Time.time);
yield return new WaitForSeconds(waitTime);
print("WaitAndPrint " + Time.time);
}
}
结果是输出 Starting 0 Start协程 0 WaitAndPrint 2.001024 Done 2.001024
第三个例子
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
IEnumerator Start()
{
print("Start开始 " + Time.time);
StartCoroutine("DoSomething", 2.0f);
yield return new WaitForSeconds(1);
StopCoroutine("DoSomething");
print("start结束 " + Time.time);
}
IEnumerator DoSomething(float someParameter)
{
while (true)
{
print("Start协程" + Time.time);
yield return null;
print("协程完成" + Time.time);
}
}
}
结果是输出 Start开始 0 Start协程0 协程完成0.02 Start协程0.02 协程完成0.3533334 Start协程0.3533334 … 协程完成0.99992 Start协程0.99992 协程完成1.001271 Start协程1.001271 start结束 1.001271
官方说这是invoke的替代用法 但但这有误差完全不想用
第四个例子
using System.Collections;
using UnityEngine;
public class ExampleClass : MonoBehaviour
{
void Start()
{
print("Start开始 " + Time.time);
StartCoroutine(coroutineA());
print("start结束 " + Time.time);
}
IEnumerator coroutineA()
{
print("Start协程A" + Time.time);
yield return new WaitForSeconds(1.0f);
yield return StartCoroutine(coroutineB());
print("协程A完成" + Time.time);
}
IEnumerator coroutineB()
{
print("Start协程B" + Time.time);
yield return new WaitForSeconds(2.5f);
print("协程B完成" + Time.time);
}
}
结果是输出 Start开始 0 Start协程A0 start结束 0 Start协程B1.000296 协程B完成3.500929 协程A完成3.500929
测试例1 null
using System.Collections;
using UnityEngine;
public class ExampleClass : MonoBehaviour
{
void Start()
{
print("Start开始 " + Time.time);
StartCoroutine(coroutineA());
print("start结束 " + Time.time);
}
IEnumerator coroutineA()
{
print("Start协程A" + Time.time);
yield return null;
print("协程A完成" + Time.time);
}
}
结果是输出 Start开始 0 Start协程A0 start结束 0 协程A完成0.02
测试例2 while(true){yield return null;}
using System.Collections;
using UnityEngine;
public class ExampleClass : MonoBehaviour
{
void Start()
{
print("Start开始 " + Time.time);
StartCoroutine(coroutineA());
print("start结束 " + Time.time);
}
IEnumerator coroutineA()
{
while (true)
{
print("Start协程A" + Time.time);
yield return null;
print("协程A完成" + Time.time);
}
}
}
结果是输出 Start开始 0 Start协程A0 start结束 0 协程A完成0.02 Start协程A0.02 协程A完成0.3533334 Start协程A0.3533334 … 结合官方例1结论 只要有while true 不管yield return是 null还是 new WaitForSeconds 就是无限输出
测试例3 官方例4 去除 yield return new WaitForSeconds(1.0f);
using System.Collections;
using UnityEngine;
public class ExampleClass : MonoBehaviour
{
void Start()
{
print("Start开始 " + Time.time);
StartCoroutine(coroutineA());
print("start结束 " + Time.time);
}
IEnumerator coroutineA()
{
print("Start协程A" + Time.time);
yield return StartCoroutine(coroutineB());
print("协程A完成" + Time.time);
}
IEnumerator coroutineB()
{
print("Start协程B" + Time.time);
yield return new WaitForSeconds(2.5f);
print("协程B完成" + Time.time);
}
}
结果是输出 Start开始 0 Start协程A0 Start协程B0 start结束 0 协程B完成2.500149 协程A完成2.500149 结论是StartCoroutine可以作为标准协程结束的条件
FIxedUpdate是精确的0.02 跟timeScale有关但却不受影响 https://docs.unity3d.com/ScriptReference/WaitForSeconds.html https://docs.unity3d.com/ScriptReference/Time-timeScale.html Time.timeScale也是1 而输出时就是2.001左右 每次都会不同 官方文档说的可能会不同 但我没法判断是不是那种情况 然后官方说了WaitForSecondsRealtime 未缩放的 但时间也不是精确的2秒 (居然小于2)(看来计时器也不能使用协程 不精确)
Coroutine官方文档 协程是一个可以暂停执行(yield)直到给定的 YieldInstruction完成的函数。 https://docs.unity3d.com/ScriptReference/Coroutine.html 第一个例子使用了WaitForSeconds 时间不精确
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
IEnumerator Start()
{
print("Starting " + Time.time);
yield return StartCoroutine("WaitAndPrint");
print("Done " + Time.time);
}
IEnumerator WaitAndPrint()
{
print("Start协程" + Time.time);
yield return new WaitForSeconds(5);
print("协程完成" + Time.time);
}
}
结果是输出 Starting 0 Start协程0 协程完成5.000767 Done 5.000767 结论 StartCoroutine可以作为start协程结束的条件
第二个例子没有使用WaitForSeconds 时间也不精确 也是是2.001左右; 第二个例子区别就是介绍了变量 其他一样
IEnumerator Start() 就是一种特殊的自己启动的协程 https://forum.unity.com/threads/why-change-void-start-to-ienumerator-start.455280/ https://answers.unity.com/questions/754968/can-monobehaviorstart-return-an-ienumerator-hint-y.html
|