2022-04-21 Unity基础2——MonoBehaviour的重要内容

一、延迟函数

​ 延迟函数顾名思,就是会延时执行的函数
​ 我们可以自己设定延时要执行的函数和具体延时的时间,是 MonoBehaviour 基类中实现好的方法

​ 脚本依附对象失活或者脚本自己失活,延迟函数可以继续执行,不会受到影响的

​ 脚本依附对象销毁或者脚本移除,延迟函数无法继续执行

(一)延迟函数

// 1.延迟函数
// Invoke
// 参数一:函数名 字符串
// 参数二:延迟时间 秒为单位
Invoke(nameof(DelayDoSomething), 1);

private void DelayDoSomething() {
    print("延时执行的函数");
}

​ 注意:

  1. 延时函数第一个参数传入的是函数名字符串

  2. 延时函数没办法传入参数,只有包裹一层

    例如,调用 TestFun 时,将参数传在 DelayDoSomething 中

    调用其他对象 t 的方法时,也需要包裹一层

private void DelayDoSomething() {
    TestFun(2);
    
    t.TestFun();
}

private void TestFun(int i) {
    print("传入参数" + i);
}

private void TestFun() {
    print("无参重载");
}
  1. 函数名必须是该脚本上申明的函数

(二)延迟重复执行函数

// 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);
    }
}

(三)yield return 不同内容的含义

// 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;

(四)协程受对象和组件失活销毁的影响

​ 协程开启后
​ 组件和物体销毁,协程不执行
​ 物体失活协程不执行,组件失活协程执行

(五)总结

  1. Unity 支持多线程,只是新开线程无法访问主线程中 Unity 相关内容

    一般主要用于进行复杂逻辑运算或者网络消息接收等等

    注意:Unity 中的多线程一定记住关闭

  2. 协同程序不是多线程,它是将线程中逻辑进行分时执行,避免卡顿

  3. 继承 MonoBehavior 的类都可以使用协程

  4. 开启协程方法、关闭协程方法

  5. yield return 返回的内容对于我们的意义

  6. 协程只有当组件单独失活时不受影响,其它情况协程会停止

三、协程原理

(一)协程本质

​ 协程可以分成两部分:

  1. 协程函数本体

    协程本体就是一个能够中间暂停返回的函数

  2. 协程调度器

    协程调度器是 Unity 内部实现的,会在对应的时机帮助我们继续执行协程函数

    Unity 只实现了协程调度部分,协程的本体本质上就是一个 C# 的迭代器方法

(二)协程本体实现

  1. 实现 yield return 类型的类
public class TestClass
{
    public int time;

    public TestClass(int time) {
        this.time = time;
    }
}
  1. 迭代器函数
private IEnumerator Test() {
    print("第一次执行");
    yield return 1;
    print("第二次执行");
    yield return 2;
    print("第三次执行");
    yield return "123";
    print("第四次执行");
    yield return new TestClass(10);
}
  1. 手动模拟协程函数
// 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 定义的一些规则

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔗理苦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值