Unity中自定义协程的简单实现

ops/2025/2/15 16:08:22/

在 Unity 中,协程(Coroutine)是一种非常强大的工具,它允许我们在不阻塞主线程的情况下,将代码的执行分成多个步骤,在不同的帧中执行。

Unity中协程实现原理
迭代器与状态机:本质上是基于C#的迭代器和状态机实现的。迭代器允许函数暂停和恢复执行,协程函数使用 yield return 语句暂停,保存当前状态,下次被调用时从暂停处继续。Unity在底层通过状态机管理协程状态,记录执行位置和局部变量等。
消息循环与时间管理:Unity的消息循环在每一帧检查协程状态。当协程 yield return 一个条件或等待时间时,Unity记录该条件,在后续帧中检查条件是否满足,满足则恢复协程执行。
执行队列与调度:Unity维护协程执行队列,按添加顺序或优先级调度协程。协程加入队列后,等待Unity根据帧循环和条件判断调度执行。

要实现自定义协程需用到一个暂停指令和协程的MoveNext方法:
1.YieldInstruction:用于实现协程的暂停指令,所有具体的暂停指令都需要继承自该类,并实现IsDone方法,用于判断暂停是否完成。
2.MoveNext方法:通过不断调用该方法,检测协程的暂停条件是否成立,如果条件成立,协程从暂停处继续执行,否则协程不会继续执行。

定义一个暂停指令基类:

public abstract class YieldInstruction
{public abstract bool IsDone();
}

定义一个暂停指令:重写IsDone函数

public class WaitForFrames : YieldInstruction
{public override bool IsDone(){remainingFrames--;return remainingFrames <= 0;}
}

 自定义一个协程类:它需要包含暂停指令、需要执行的迭代器函数、还要实现一个MoveNext函数,具体实现如下:

    public bool MoveNext(){//首先判断暂停指令是否存在if (currentYield != null){if (!currentYield.IsDone()){// 当前 YieldInstruction 未完成,继续等待return true;}// 当前 YieldInstruction 完成,重置currentYield = null;}//如果迭代器的MovenNext方法返回true则协程等待if (routine.MoveNext()){currentYield = routine.Current as YieldInstruction;return true;}// 协程执行完毕return false;}

自定义调度器: 需要实现StartCoroutine,StopCoroutine和Update函数

    // 存储待执行的协程列表private List<CustomCoroutine> coroutines = new List<CustomCoroutine>();// 启动一个协程public CustomCoroutine StartCoroutine(IEnumerator routine){CustomCoroutine coroutine = new CustomCoroutine(routine);coroutines.Add(coroutine);return coroutine;}// 更新协程调度器,需要在每一帧调用public void Update(){for (int i = coroutines.Count - 1; i >= 0; i--){coroutines[i].MoveNext();}}public void StopCoroutine(CustomCoroutine routine){coroutines.Remove(routine);}public void StopAllCoroutine(){coroutines.Clear();}

调用:

CustomCoroutineScheduler scheduler = new CustomCoroutineScheduler();void Start(){// 启动一个协程scheduler.StartCoroutine(TestCoroutine());}void Update(){scheduler.Update();}IEnumerator TestCoroutine(){Debug.Log("Coroutine started");yield return new WaitForFrames(3);Debug.Log("Waited for 3 frames");Debug.Log("Coroutine ended");}

 结果:

其他有用的链接:

KarnageUnity/CustomCoroutine: Two C# classes demonstrating how Unity implements Coroutines (github.com)

gohbiscuit/UnityCustomCoroutine: Unity Custom Coroutine class can be use to handle multiple or nested coroutine (github.com)

Ellpeck/Coroutine: A simple implementation of Unity's Coroutines to be used for any C# project (github.com)

utamaru/unity3d-extra-yield-instructions:Unity3D 协程的其他自定义 yield 指令 (github.com) 

 


http://www.ppmy.cn/ops/158624.html

相关文章

从 ClickHouse 到 Apache Doris:在网易云音乐日增万亿日志数据场景下的落地

导读&#xff1a;日志数据已成为企业洞察系统状态、监控网络安全及分析业务动态的宝贵资源。网易云音乐引入 Apache Doris 作为日志库新方案&#xff0c;替换了 ClickHouse。解决了 ClickHouse 运维复杂、不支持倒排索引的问题。目前已经稳定运行 3 个季度&#xff0c;规模达到…

SpringCloud中Sentinel基础场景和异常处理

Sentinel 是一个由 阿里巴巴 开源的分布式系统流量控制组件&#xff0c;专注于为微服务架构提供流量控制、熔断降级、系统负载保护等功能。它特别适用于高并发、高可用性的分布式系统&#xff0c;能够帮助开发者保护系统免于因流量过载、系统崩溃、依赖不可用等情况而导致的服务…

【Elasticsearch源码解读】代码包结构概述

Elasticsearch的代码库包含多个包&#xff0c;每个包负责不同的功能。以下是这些包的主要功能&#xff1a; #### action 封装了Elasticsearch的各种操作&#xff0c;如索引、搜索、删除等&#xff0c;提供了与集群交互的接口。 #### bootstrap 包含启动Elasticsearch节点所…

双指针思想

双指针&#xff08;Two Pointers&#xff09;是一种常用的算法思想&#xff0c;通过使用两个指针&#xff08;通常是下标或迭代器&#xff09;在数组、链表或字符串中协同工作&#xff0c;高效解决一些问题。双指针的核心思想是通过指针的移动来减少时间复杂度&#xff0c;通常…

E8移动建模关联建模表单,写入无数据

场景&#xff1a;移动建模新建一个招聘页面&#xff0c;每次通过移动建模写入建模表数据&#xff0c;建模表的值都要权限重构才可看见&#xff0c;且明细无数据。 排查原因&#xff1a;移动建模提交后返回的ID值为空 正常情况下提交数据应该要返回一个ID值如下&#xff1a; 解…

AI如何与DevOps集成,提升软件质量效能

随着技术的不断演进&#xff0c;DevOps和AI的融合成为推动软件开发质量提升的重要力量。传统的DevOps已经为软件交付速度和可靠性打下了坚实的基础&#xff0c;而随着AI技术的加入&#xff0c;DevOps流程不仅能提升效率&#xff0c;还能在质量保障、缺陷预测、自动化测试等方面…

Jenkins 新建配置Pipeline任务 三

Jenkins 新建配置Pipeline任务 三 一. 登录 Jenkins 网页输入 http://localhost:8080 输入账号、密码登录 一个没有创建任务的空 Jenkins 二. 创建 任务 图 NewItem 界面左上角 New Item 图NewItemSelect 1.Enter an item name&#xff1a;输入任务名 2.Select an ite…

超融合技术(Hyper-Converged Infrastructure,HCI)

超融合技术&#xff08;HCI&#xff0c;Hyper-Converged Infrastructure&#xff09;是一种将计算、存储、网络等多种基础设施资源在同一个平台中集成的技术。它的核心思想是通过软件定义&#xff08;Software-Defined&#xff09;来提供一个高度集成的硬件和软件平台&#xff…