延迟函数顾名思,就是会延时执行的函数
我们可以自己设定延时要执行的函数和具体延时的时间,是 MonoBehaviour 基类中实现好的方法
脚本依附对象失活或者脚本自己失活,延迟函数可以继续执行,不会受到影响的
脚本依附对象销毁或者脚本移除,延迟函数无法继续执行
// 1.延迟函数
// Invoke
// 参数一:函数名 字符串
// 参数二:延迟时间 秒为单位
Invoke(nameof(DelayDoSomething), 1);
private void DelayDoSomething() {
print("延时执行的函数");
}
注意:
延时函数第一个参数传入的是函数名字符串
延时函数没办法传入参数,只有包裹一层
例如,调用 TestFun 时,将参数传在 DelayDoSomething 中
调用其他对象 t 的方法时,也需要包裹一层
private void DelayDoSomething() {
TestFun(2);
t.TestFun();
}
private void TestFun(int i) {
print("传入参数" + i);
}
private void TestFun() {
print("无参重载");
}
// 2.延迟重复执行函数
// InvokeRepeating
// 参数一:函数名字符串
// 参数二:第一次执行的延迟时间
// 参数三:之后每次执行的间隔时间
InvokeRepeating(nameof(DelayRe), 5, 1);
private void DelayRe() {
print("重复执行");
}
注意:它的注意事项和延时函数一致
// 3.取消延迟函数
// 3-1取消该脚本上的所有延时函数执行
CancelInvoke();
// 3-2指定函数名取消
// 只要取消了指定延迟 不管之前该函数开启了多少次 延迟执行 都会统一取消
CancelInvoke(nameof(DelayDoSomething));
// 4.判断是否有延迟函数
if (IsInvoking()) print("存在延迟函数");
if (IsInvoking(nameof(DelayDoSomething))) print("存在延迟函数DelayDoSomething");
Unity 支持多线程,但是新开线程无法访问 Unity 相关对象的内容
注意:Unity 中的多线程,要记住关闭
协同程序简称协程,它是“假”的多线程,它不是多线程
它的主要作用是将代码分时执行,不卡主线程
简单理解,是把可能会让主线程卡顿的耗时的逻辑分时分步执行
主要使用场景:
区别:
// 继承MonoBehavior的类 都可以开启 协程函数
// 第一步:申明协程函数
// 协程函数2个关键点
// 1-1返回值为IEnumerator类型及其子类
// 1-2函数中通过 yield return 返回值; 进行返回
// 第二步:开启协程函数
// 协程函数 是不能够 直接这样去执行的!!!!!!!
// 这样执行没有任何效果
// MyCoroutine(1, "123");
// 常用开启方式
// IEnumerator ie = MyCoroutine(1, "123");
// StartCoroutine(ie);
Coroutine c1 = StartCoroutine(MyCoroutine(1, "123"));
Coroutine c2 = StartCoroutine(MyCoroutine(1, "123"));
Coroutine c3 = StartCoroutine(MyCoroutine(1, "123"));
// 第三步:关闭协程
// 关闭所有协程
StopAllCoroutines();
// 关闭指定协程
StopCoroutine(c1);
// 关键点一: 协同程序(协程)函数 返回值 必须是 IEnumerator或者继承它的类型
private IEnumerator MyCoroutine(int i, string str) {
print(i);
// 关键点二: 协程函数当中 必须使用 yield return 进行返回
yield return null;
print(str);
yield return new WaitForSeconds(1f);
print("2");
yield return new WaitForFixedUpdate();
print("3");
// 主要会用来 截图时 会使用
yield return new WaitForEndOfFrame();
while (true) {
print("5");
yield return new WaitForSeconds(5f);
}
}
// 1.下一帧执行
yield return 数字;
yield return null;
// 在Update和LateUpdate之间执行
// 2.等待指定秒后执行
yield return new WaitForSeconds(秒);
// 在Update和LateUpdate之间执行
// 3.等待下一个固定物理帧更新时执行
yield return new WaitForFixedUpdate();
// 在FixedUpdate和碰撞检测相关函数之后执行
// 4.等待摄像机和GUI渲染完成后执行
yield return new WaitForEndOfFrame();
// 在LateUpdate之后的渲染相关处理完毕后之后
// 5.一些特殊类型的对象 比如异步加载相关函数返回的对象
// 之后讲解 异步加载资源 异步加载场景 网络加载时再讲解
// 一般在Update和LateUpdate之间执行
// 6.跳出协程
yield break;
协程开启后
组件和物体销毁,协程不执行
物体失活协程不执行,组件失活协程执行
Unity 支持多线程,只是新开线程无法访问主线程中 Unity 相关内容
一般主要用于进行复杂逻辑运算或者网络消息接收等等
注意:Unity 中的多线程一定记住关闭
协同程序不是多线程,它是将线程中逻辑进行分时执行,避免卡顿
继承 MonoBehavior 的类都可以使用协程
开启协程方法、关闭协程方法
yield return 返回的内容对于我们的意义
协程只有当组件单独失活时不受影响,其它情况协程会停止
协程可以分成两部分:
协程本体就是一个能够中间暂停返回的函数
协程调度器是 Unity 内部实现的,会在对应的时机帮助我们继续执行协程函数
Unity 只实现了协程调度部分,协程的本体本质上就是一个 C# 的迭代器方法
public class TestClass
{
public int time;
public TestClass(int time) {
this.time = time;
}
}
private IEnumerator Test() {
print("第一次执行");
yield return 1;
print("第二次执行");
yield return 2;
print("第三次执行");
yield return "123";
print("第四次执行");
yield return new TestClass(10);
}
// 1.协程函数本体
// 如果我们不通过 开启协程方法执行协程
// Unity的协程调度器是不会帮助我们管理协程函数的
IEnumerator ie = Test();
// 但是我们可以自己执行迭代器函数内容
ie.MoveNext(); // 会执行函数中内容遇到 yield return为止的逻辑,这里会打印 "第一次执行"
print(ie.Current); // 得到 yield return 返回的内容,这里将打印 1
ie.MoveNext(); // 这里会打印 "第二次执行"
print(ie.Current); // 这里将打印 2
ie.MoveNext(); // 这里会打印 "第三次执行"
print(ie.Current); // 这里将打印 "123"
ie.MoveNext(); // 这里会打印 "第四次执行"
TestClass tc = ie.Current as TestClass;
print(tc.time); // 这里将打印 10
// MoveNext 返回值 代表着 是否到了结尾(这个迭代器函数 是否执行完毕)
while (ie.MoveNext()) print(ie.Current);
继承 MonoBehavior 后,开启协程,相当于是把一个协程函数(迭代器)放入 Unity 的协程调度器中帮助我们管理进行执行
具体的 yield return 后面的规则,也是 Unity 定义的一些规则
你可以简化理解迭代器函数
C# 看到迭代器函数和 yield return 语法糖,就会把原本是一个的函数变成"几部分",我们可以通过迭代器从上到下遍历这"几部分"进行执行,就达到了将一个函数中的逻辑分时执行的目的
而协程调度器就是利用迭代器函数返回的内容来进行之后的处理,比如 Unity 中的协程调度器
根据 yield return 返回的内容 决定了下一次在何时继续执行迭代器函数中的"下一部分"
入 Unity 的协程调度器中帮助我们管理进行执行
具体的 yield return 后面的规则,也是 Unity 定义的一些规则