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

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

在 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) 

 

相关文章:

  • linux 查看设备中的摄像头迅速验证设备号
  • 畅聊deepseek-r1,SiliconFlow 硅基流动注册+使用
  • 一文讲清前端热更新
  • npm 私服使用介绍
  • docker搭建redis-cluster
  • DeepSeek、Kimi、文心一言、通义千问:AI 大语言模型的对比分析
  • 多媒体软件安全与授权新范例,用 CodeMeter 实现安全、高效的软件许可管理
  • Linux系统离线部署MySQL详细教程(带每步骤图文教程)
  • 网络工程师 (29)CSMA/CD协议
  • kron积计算mask类别矩阵
  • python连点器
  • 【STM32】舵机SG90
  • 部署 DeepSeek R1各个版本所需硬件配置清单
  • 网络分析工具—WireShark的安装及使用
  • 【自然语言处理】TextRank 算法提取关键词、短语、句(Python源码实现)
  • 【学习笔记】for、forEach会不会被await阻塞
  • 【2024~2025年备受关注的AI大模型】
  • 杂记:STM32 调试信息打印实现方式
  • 关于 IoT DC3 中驱动(Driver)的理解
  • SolidWorks C# How
  • 网络主播直播泄机密,别让这些“小事”成威胁国家安全的“突破口”
  • 上财发布“AI+课程体系”,人工智能如何赋能财经教育?
  • 报告:4月份新增发行的1763亿元专项债中,投向房地产相关领域约717亿元
  • 早期投资人蜂巧资本清仓泡泡玛特套现超22亿港元,称基金即将到期
  • 迪拜金融市场CEO:2024年市场表现出色,超八成新投资者来自海外
  • 多人称华为手机忽现拍照模糊疑存缺陷,售后回应:主摄像头故障