封装和桥接Unity 协程体系

简介

        协程(Coroutine)在C#中是一种特殊的函数,它允许开发者编写可以暂停执行并在未来某个时刻恢复执行的代码块。协程通常用于实现异步操作,如延时执行、等待某个事件发生、或者分段执行复杂的任务。在Unity游戏引擎中,协程尤为重要,因为它们可以在不阻塞主线程的情况下执行这些操作。

        C#协程的实现依赖于迭代器(Iterator)和状态机(State Machine)。当编写一个协程时,你实际上是定义了一个返回IEnumerator类型的方法。这个方法内部可以包含yield语句,用于控制协程的执行流程。yield return语句可以返回一个值并暂停协程,直到下一帧或特定条件满足时再次执行。yield break语句则会完全结束协程的执行。

Unity 已经有了Async Operation,为什么还要二次封装或桥接呢?

        当然,它在某些情况下可以帮助我们解决很多令人很头疼的问题!例如:要等待一组Async Operation对象,同时要监控他们的进度;再例如,需要同时等待数目不确定的Async Operation,但是他们却来自于不同的系统;又或者,希望一段逻辑去控制Yield的完成状态,那么在这种情况下,桥接和封装是最好的选择。

它可以实现什么效果呢?

        下面这段代码展示了如何使用逻辑控制Yield Completed State,当W按键被按下后,yield return new .... 下面的代码才会被执行。

    private IEnumerator Start ()
    { 
        Debug.Log($"Start: {Time.time}");
        yield return new XAsyncOperationCondition(a=>Pass);
        Debug.Log($"End: {Time.time}");
    }

    private void Update ()
    {
        if ( Input.GetKey(KeyCode.W) )
        {
            Pass = true;
        }
    }

        下面这段代码展示了如何将来自不同系统的Async Operation 整合在一起,这对于同时处理不同管线的资产加载进度时非常有帮助。

    XAsyncOperationGroup HandleGroup;
    private IEnumerator Start ()
    {
        var url = "https://img0.baidu.com/it/u=1799694557,1475747482&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=750"; 
        var fromWebHandle =  new XAsyncOperationWebTextureRequest(UnityWebRequestTexture.GetTexture(url).SendWebRequest());
        var fromResourceHandle = new XAsyncOperationResourceRequest<Texture>(Resources.LoadAsync("default.jpg"));
        var fromAddressableHandle = new XAsyncOperationAddressable<Texture>(Addressables.LoadAssetAsync<Texture>("default"));

        HandleGroup = new XAsyncOperationGroup(fromWebHandle, fromResourceHandle, fromAddressableHandle);

        yield return HandleGroup;

        //> fromWebHandle.Result
        //> fromResourceHandle.Result
        //> fromAddressableHandle.Result
    }

    private void Update ()
    {
        if ( HandleGroup != null )
        {
            Debug.Log($"载入进度:{HandleGroup.PercentComplete}");
        }
    }

如果你想进一步了解他们,下面的UML展示了他们是如何工作的

UML

        他被分成了两部分,绿色节点主要用来统计进度,灰色节点主要用来桥接不同管线的资源,绿色的节点通过访问一个全局静态的GameObject实现了在不需要MonoBehaviour的情况下投递协程作业。

核心代码示例
//> XGlobalCoroutine.cs
//> Create by UniMark

using System.Collections;
using UnityEngine;

namespace XF.Internal
{
    internal class XGlobalCoroutine : MonoBehaviour 
    {
        internal static XGlobalCoroutine Behaviour;
        public static XGlobalCoroutine Instance
        {
            get
            {
                if (Behaviour == null)
                {
                    GameObject root = new GameObject($"[Global]{typeof(XGlobalCoroutine).Name}");
                    GameObject.DontDestroyOnLoad(root);
                    Behaviour = root.AddComponent<XGlobalCoroutine>();
                }
                return Behaviour;
            }
        }
    }

    internal static class XAsyncOperationExtends 
    {
        internal static void StartCoroutine(this XAsyncOperation operation, IEnumerator routine)
        {
            if (routine == null) return;
            XGlobalCoroutine.Instance.StartCoroutine(routine);
        }

        internal static void StopCoroutine(this XAsyncOperation operation, IEnumerator routine)
        {
            if (routine == null) return;
            XGlobalCoroutine.Instance.StopCoroutine(routine);
        }
    }
}
//> XAsyncOperation.Implement.cs
//> Create by UniMark

using System;
using System.Collections;

namespace XF
{
    /// <summary>
    /// 异步操作的抽象类
    /// </summary>
    public abstract class XAsyncOperation : IEnumerator
    {
        /// <summary>
        /// 是否完成
        /// </summary>
        public bool IsComplete { get; private set; }
        /// <summary>
        /// 完成百分比,取值[0~1]
        /// </summary>
        public virtual float PercentComplete { get; protected set; }
        /// <summary>
        /// 期间发生的错误信息,如果没有返回string.empty
        /// </summary>
        public string Error { get; internal set; }

        /// <summary>
        /// 完成时调用的回调
        /// 在完成前注册的回调会在完成时统一调用一次
        /// 在完成后注册的回调会在注册时立即执行一次
        /// </summary> 
        public virtual event Action<XAsyncOperation> OnCompleted
        {
            add
            {
                if (IsComplete)
                    value?.Invoke(this);
                else
                    CompletedEvent += value;
            }
            remove
            {
                CompletedEvent -= value;
            }
        }
        protected Action<XAsyncOperation> CompletedEvent;
        protected virtual void SetComplete()
        {
            IsComplete = true;
            PercentComplete = 1;
            CompletedEvent?.Invoke(this);
            CompletedEvent = null;
        }

        public virtual void Release() { }

        #region 接口 
        object IEnumerator.Current => null; 
        bool IEnumerator.MoveNext() => !IsComplete; 
        void IEnumerator.Reset() { }
        #endregion
    }
}
完整代码示例

unity_custom_async_operation

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/870144.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Conda和Pip有什么区别?

conda和pip是Python中两种常用的包管理工具&#xff0c;它们在用途、包来源以及环境管理等方面存在区别。以下是具体分析&#xff1a; 用途 conda&#xff1a;conda是Anaconda发行版中的包管理工具&#xff0c;可以管理包括非Python软件包在内的各种包。它是一个全面的环境管理…

【数据结构】建堆算法复杂度分析及TOP-K问题

【数据结构】建堆算法复杂度分析及TOP-K问题 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;数据结构 文章目录 【数据结构】建堆算法复杂度分析及TOP-K问题前言一.复杂度分析1.1向下建堆复杂度1.2向上建堆复杂度1.3堆排序复杂度 二.TOP-K问…

Leetcode—769. 最多能完成排序的块【中等】

2024每日刷题&#xff08;149&#xff09; Leetcode—769. 最多能完成排序的块 实现代码 class Solution { public:int maxChunksToSorted(vector<int>& arr) {int ans 0;int mx INT_MIN;for(int i 0; i < arr.size(); i) {mx max(arr[i], mx);if(mx i) {a…

数据库安全:MySQL安全配置,MySQL安全基线检查加固

「作者简介」:冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础著作 《网络安全自学教程》,适合基础薄弱的同学系统化的学习网络安全,用最短的时间掌握最核心的技术。 这一章节我们需要知道MySQL的安全基线标准和加固方式。 MySQL基线检查 1、更新…

Cannot access org.springframework.context.ConfigurableApplicationContext

Cannot access org.springframework.context.ConfigurableApplicationContext SpringApplication.run曝红 解决方案&#xff1a; File -> Invalidate Cache and Restart 如果对你有用就点个赞&#xff01;

项目实战——外挂开发(30小时精通C++和外挂实战)

项目实战——外挂开发&#xff08;30小时精通C和外挂实战&#xff09; 外挂开发1-监控游戏外挂开发2-秒杀僵尸外挂开发3-阳光地址分析外挂开发4-模拟阳光外挂开发5-无限阳光 外挂开发1-监控游戏 外挂的本质 有两种方式 1&#xff0c;修改内存中的数据 2&#xff0c;更改内存中…

【Stable Diffusion】AI生成新玩法:图像风格迁移

【Stable Diffusion】 AI生成新玩法&#xff1a;图像风格迁移 1 背景导入 你是否曾梦想过让自己融入梵高的星空之中 或是将一幅风景画赋予毕加索的立体主义之魂 还是把人物送进宫崎骏的动画世界&#xff1f; 下面让我们来看看如何通过 Stable Diffusion 实现在图像中玩…

Java面试八股之什么是声明式事务管理,spring怎么实现声明式事务管理?

什么是声明式事务管理&#xff0c;spring怎么实现声明式事务管理&#xff1f; 声明式事务管理是一种编程范式&#xff0c;它允许开发人员通过声明性的配置或注解&#xff0c;而不是硬编码事务处理逻辑&#xff0c;来指定哪些方法或类应该在其上下文中执行事务。这种方法将事务…

【Gin】深度解析:在Gin框架中优化应用程序流程的责任链设计模式(上)

【Gin】深度解析&#xff1a;在Gin框架中优化应用程序流程的责任链设计模式(上) 大家好 我是寸铁&#x1f44a; 【Gin】深度解析&#xff1a;在Gin框架中优化应用程序流程的责任链设计模式(上)✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 前言 本次文章分为上下两部分&#xf…

学习React(描述 UI)

React 是一个用于构建用户界面&#xff08;UI&#xff09;的 JavaScript 库&#xff0c;用户界面由按钮、文本和图像等小单元内容构建而成。React 帮助你把它们组合成可重用、可嵌套的 组件。从 web 端网站到移动端应用&#xff0c;屏幕上的所有内容都可以被分解成组件。在本章…

MongoDB教程(二十一):MongoDB大文件存储GridFS

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、GridFS…

Windows版MySQL5.7解压直用(如何卸载更换位置重新安装)

文章目录 停止mysql进程及服务迁移整个mysql文件夹删除data重启计算机重新安装 停止mysql进程及服务 net stop mysql mysqld -remove mysql迁移整个mysql文件夹 删除data 重启计算机 shutdown -r -t 0重新安装 https://blog.csdn.net/xzzteach/article/details/137723185

H3CNE(vlan的基础配置)

目录 9.1 传统以太网的问题 9.2 VLAN基础实现的原理 示例一&#xff08;vlan配置的基础实现&#xff09;&#xff1a; 示例二&#xff08;交换机间配置trunk&#xff09;&#xff1a; 9.3 hybrid接口类型与打标签的原理 示例三&#xff08;配置hybrid接口&#xff09;&#x…

【深度学习】LLaMA-Factory 大模型微调工具, 大模型GLM-4-9B Chat ,微调与部署 (2)

文章目录 数据准备chat评估模型导出模型部署总结 资料&#xff1a; https://github.com/hiyouga/LLaMA-Factory/blob/main/README_zh.md https://www.53ai.com/news/qianyanjishu/2015.html 代码拉取&#xff1a; git clone https://github.com/hiyouga/LLaMA-Factory.git cd …

STM32串口(串口基础)

串口整个东西可以说但凡你要碰单片机&#xff0c;想做点上点档次的东西的话那你就包用它的。32的串口配置并不难&#xff0c;哪怕是比起51其实也难不到哪去。 目录 一.通信基础 1.通信方式 2.通信速率 二.串口基础 1.串口的数据帧结构&#xff08;协议&#xff09; 2.ST…

【Godot4.2】GodotXML插件 - 解析和生成XML

概述 近期在研究Godot的XML和SVG解析&#xff0c;Godot提供了XMLParser类型&#xff0c;但本身只提供了低级的XML解析接口和功能&#xff0c;想要完成完整的XML文档解析和存储可能还需要在其基础上编写类或功能&#xff0c;就像我在昨天&#xff08;2024年7月20日&#xff09;…

Web开发:图片九宫格与非九宫格动态切换效果(HTML、CSS、JavaScript)

目录 一、业务需求 二、实现思路 三、实现过程 1、基础页面 2、图片大小调整 3、图片位置调整 4、鼠标控制切换 5、添加过渡 四、完整代码 一、业务需求 默认显示基础图片&#xff1b; 当鼠标移入&#xff0c;使用九宫格效果展示图片&#xff1b; 当鼠标离开&#…

基于Cobbler实现多版本系统批量部署

一、实验题目 基于Cobbler实现多版本系统批量部署 二、实验目的 通过Cobbler&#xff0c;实验旨在实现无需人工干预即可自动安装多个版本的操作系统。这可以大大提高机房设备或服务器集群的部署效率&#xff0c;减少人力成本和操作错误。 三、实验环境 centos7.9并安装Cob…

机器学习 | 回归算法原理——多重回归

Hi&#xff0c;大家好&#xff0c;我是半亩花海。接着上次的多项式回归继续更新《白话机器学习的数学》这本书的学习笔记&#xff0c;在此分享多重回归这一回归算法原理。本章的回归算法原理基于《基于广告费预测点击量》项目&#xff0c;欢迎大家交流学习&#xff01; 目录 一…

【Django】anaconda环境变量配置及配置python虚拟环境

文章目录 配置环境变量配置python虚拟环境查看conda源并配置国内源在虚拟环境中安装django 配置环境变量 control sysdm.cpl,,3笔者anaconda安装目录为C:\ProgramData\anaconda3 那么需要加入path中的有如下三个 C:\ProgramData\anaconda3 C:\ProgramData\anaconda3\Scripts C:…