当前位置: 首页 > news >正文

Unity基础-协程

Unity基础-协程

四、协程

概述

协程(Coroutine),本质上并不是多线程,而是在当前线程中将代码分时执行,不卡主线程。可以理解为,协程会把可能使主线程卡顿的程序分时分布进行。
协程通常用来:加载场景,异步加载文件,异步下载文件,批量创建物体防止卡顿。

协程与线程的区别

  • 新开一个线程是独立的一个管道,和主线程并行。Unity支持多线程,但是新开的线程无法访问Unity中的任何东西,只能靠中间枢纽和Unity主线程联络。
  • 新开一个协程是在原线程之上开启,进行逻辑分时分布执行。

协程的使用

协程可以分为两部分:1.协程函数本体,2.协程调度器。
协程本体就是一个能够中间暂停返回的函数。协程调度器是Unity内部实现的,会在对应的时机帮助我们继续执行协程函数。Unity只实现了协程调度的部分。
协同函数返回值必须是IEnumerator类型或者继承他的类型。

// 声明协程
IEnumerator MyCoroutineExample()
{print("111");yield return new WaitForSeconds(2);print("222");
}// 启动协程
StartCoroutine(MyCoroutineExample());// 关闭全部协程
StopAllCoroutines(); // 关闭特定协程
Coroutine co1 = StartCoroutine(MyCoroutineExample());
StopCoroutine(co1);

协程函数本体与C#迭代器

协程的本体本质上就是一个C#迭代器的方法。
C# 迭代器(Iterator)是一种特殊的方法或 get 访问器,允许你通过 yield return 语句逐步返回集合中的每个元素,而无需构建整个集合。它使得遍历自定义集合类型变得非常简单和高效。
IEnumerableIEnumerable<T> 接口的作用是使一个类型能够被 foreach 语句遍历。简单来说,只要一个类型实现了 IEnumerable (或 IEnumerable<T>),你就可以在 foreach 循环中使用它。

如果我们不通过Unity中给的开启协程的方法开启协程,Unity的协程调度器就不会帮我们管理协程函数。但是我们可以自己执行迭代器函数内容。
继承MonoBehavior后,开启协程,相当于把一个协程函数放入Unity的协程调度器中帮助我们管理进行执行,具体的 yield return 后面的规则也是Unity实现定义好的。

yield return 的含义和类型

yield return 语句是协程的核心,它控制协程的暂停和恢复时机,并可以返回不同类型的对象以实现不同的等待逻辑。

  1. 下一帧执行

    • yield return 数字; (通常 yield return 0; 或其他数字,但通常用 null)
    • yield return null;
    • UpdateLateUpdate 之间执行。
  2. 等待指定秒后执行

    • yield return new WaitForSeconds(秒);
    • UpdateLateUpdate 之间执行。
  3. 等待下一个固定物理帧更新时执行

    • yield return new WaitForFixedUpdate();
    • FixedUpdate 和碰撞检测相关函数之后执行。
  4. 等待摄像机和 GUI 渲染完成后执行

    • yield return new WaitForEndOfFrame();
    • LateUpdate 之后的渲染相关处理完毕后执行。
  5. 一些特殊类型的对象

    • 比如异步加载相关函数返回的对象(AsyncOperation)。
    • 通常在异步加载资源、异步加载场景、网络加载时使用。
    • 一般在 UpdateLateUpdate 之间执行。
  6. 跳出协程

    • yield break;:用于提前终止协程的执行。

协程应用示例:计时器与大量对象生成

习题要求
  1. 利用协程制作一个简单的秒表计时器,每秒在控制台打印当前秒数。
  2. 使用协程在场景中随机位置生成100000个立方体,确保在生成过程中不会出现明显的卡顿,这可以通过在适当的时机使用 yield return null; 实现。
代码实现
点击展开/折叠 协程实现代码
using System.Collections;
using UnityEngine;
using Random = UnityEngine.Random; // 明确指定Random命名空间,避免和System.Random冲突public class CoroutineExamples : MonoBehaviour
{int time = 0;// 启动协程void Start(){StartCoroutine(MyTimerCoroutine()); // 更名为MyTimerCoroutineStartCoroutine(CreateManyCubesCoroutine()); // 更名为CreateManyCubesCoroutine}// 计时器协程IEnumerator MyTimerCoroutine(){while (true){print("秒" + time);time++;yield return new WaitForSeconds(1);}}// 生成大量立方体协程IEnumerator CreateManyCubesCoroutine(){for (int i = 0; i < 100000; i++){GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);obj.transform.position = new Vector3(Random.Range(-100, 100), Random.Range(-100, 100), Random.Range(-100, 100));if (i % 1000 == 0) // 每生成1000个立方体暂停一帧,避免卡顿{yield return null;}}}
}

总结

你可以简化理解迭代器函数:C# 看到迭代器函数和 yield return 语法糖,就会把原本是一个的函数变成"几部分"。我们可以通过迭代器从上到下遍历这"几部分"进行执行,就达到了将一个函数中的逻辑分时执行的目的。

相关文章:

  • STL 6分配器
  • matlab画图时如何屏蔽title等函数中缺省的latex解释
  • AI销售工具开发指南:关键技术点与行业解决方案
  • 在鸿蒙HarmonyOS 5中HarmonyOS应用开发实现QQ音乐风格的播放功能
  • C++ mutex 锁的使用
  • day27/60
  • 在鸿蒙HarmonyOS 5中实现抖音风格的草稿箱功能
  • 新能源知识库(34)什么是单一制和两部制
  • 经典的多位gpio初始化操作
  • JetBrains IntelliJ IDEA插件推荐
  • Spring MVC 核心枢纽:DispatcherServlet 的深度解析与实践价值
  • Zynq multi boot及网口远程更新开发
  • .Net框架,除了EF还有很多很多......
  • 简易版抽奖活动的设计技术方案
  • 数据库管理与高可用-PostgreSQL初体验
  • 安全编程期末复习34(红色重点向下兼容)
  • 8.1.排序的基本概念
  • ArkUI-X平台差异化
  • 函数中的Callable
  • Web安全漏洞详解及解决方案
  • 京东网站建设流程/查收录
  • 吴中区住房和城乡建设局网站/西安疫情最新情况
  • 菠菜建设网站/网络营销产品策略分析
  • 济南b2c网站建设/百度一下你就知道了百度
  • 版式设计网站/水果网络营销策划书
  • 天坛网站建设/星沙网站优化seo