封装和桥接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 UniMarkusing 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 UniMarkusing 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);elseCompletedEvent += 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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(Arxiv-2023)MobileDiffusion:移动设备上即时文本到图像生成

MobileDiffusion&#xff1a;移动设备上即时文本到图像生成 Paper Title&#xff1a;MobileDiffusion: Instant Text-to-Image Generation on Mobile Devices Paper是谷歌出品 Paper地址 图 1&#xff1a;MobileDiffusion 用于 (a) 文本到图像的生成。(b) Canny 边缘到图像、风…

docker容器cuda不可用,怎么解决?

通过Docker 构建的镜像中,启动之后,发现容器内部读取不到显卡驱动nvidia-smi 1、设置 NVIDIA Docker 存储库 distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add

Docker容器基础篇

一.Docker容器简要介绍 Docker 是一个开源项目&#xff0c;旨在提供轻量级的应用容器化解决方案。它允许开发者打包应用及其所有依赖项到一个标准化的单元中&#xff0c;称为容器。这些容器可以在开发人员的工作环境中构建&#xff0c;然后轻松地在不同的计算机、服务器或云平…

Linux更换pip下载镜像源

Windows中修改pip下载源-CSDN博客 本机Linux发行版本: Rocky_linux9.4 方法一&#xff1a; [rootlocalhost ~]# mkdir /root/.pip [rootlocalhost ~]# vim /root/./.pip/pip.conf [global] index-url http://mirrors.aliyun.com/pypi/simple/[install] trusted-hostmirror…

Laravel Mix与Webpack集成:打造现代化前端开发流程

Laravel Mix与Webpack集成&#xff1a;打造现代化前端开发流程 Laravel不仅仅是一个后端框架&#xff0c;它还为前端开发提供了强大的工具。Laravel Mix是一个强大的前端集成工具&#xff0c;它使用Webpack作为底层&#xff0c;为Laravel项目提供了一系列编译和热重载功能。本…

Redis的分布式锁

目录 一、定义与原理 基于Redis的分布式锁 获取锁 释放锁 锁误删问题&#xff1a;因为key值一样,将别人的锁删掉了 锁误判问题二&#xff1a;判断锁和释放锁不是原子性的 Lua脚本 分布式锁&#xff1a;满足分布式系统或集群模式下多进程可见并且互斥的锁 分布式锁的优点…

Spring Cache常用注解

依赖代码如下&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency> 常用注解详解 1. Cacheable 作用&#xff1a;主要用于配置方法&#xff0c;使其…

Java编写SIP协议

1、编写Server代码 package com.genersoft.iot.vmp.sip; import javax.sip.*; import javax.sip.message.*; import javax.sip.header.*; import java.util.*;public class SimpleSipServer implements SipListener {private SipFactory sipFactory;private SipStack sipStack…

【前端】一文带你了解 CSS

文章目录 1. CSS 是什么2. CSS 引入方式2.1 内部样式2.2 外部样式2.3 内联样式 3. CSS 常见选择器3.1 基础选择器3.1.1 标签选择器3.1.2 类选择器3.1.3 id 选择器3.1.4 通配符选择器 3.2 复合选择器3.2.1 后代选择器 4. CSS 常用属性4.1 字体相关4.2 文本相关4.3 背景相关4.4 设…

前端必备基础【网络通信】(2024最新版)

Ajax Asynchronous Javascript and XML 的缩写&#xff0c;是使用 JS 发起网络通信的技术统称&#xff0c;具体步骤为&#xff1a; 创建 XMLHttpRequest 实例发出 HTTP 请求接收服务器传回的数据更新网页数据&#xff08;通常是部分内容&#xff0c;而不是整个网页&#xff09…

LLM - 理解 大模型 Batch 推理的 Padding Side (左填充或右填充)

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/140697827 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 使用 Left Padding (左填充) 或者 Right Padding (右填充),HuggingFac…

DBeaver安装与使用教程 免费的连接mysql数据库软件

一、DBeaver安装 &#xff08;一&#xff09;Dbeaver下载 DBeaver 是一个通用的数据库管理工具和 SQL 客户端&#xff0c;免费&#xff0c;跨平台&#xff0c;支持 MySQL, PostgreSQL, Oracle, DB2, MSSQL, Sybase, Mimer, HSQLDB, Derby, 以及其他兼容 JDBC 的数据库。 官网…

通常指的是将数据存储在远程服务器上

云存储:通常指的是将数据存储在远程服务器上,而不是本地计算机上。对于AWS(Amazon Web Services),云存储服务主要由S3(Simple Storage Service)提供。boto3:这是AWS的官方Python SDK,它允许Python开发者与AWS服务进行交互。S3():在boto3中,S3()是一个客户端对象,用…

C语言经典习题24

文件操作习题 一 编程删除从C盘home文件夹下data.txt文本文件中所读取字符串中指定的字符&#xff0c;该指定字符由键盘输入&#xff0c;并将修改后的字符串以追加方式写入到文本文件C:\home\data.txt中。 #include<stdio.h> main() { char s[100],ch; int i;…

带你学会Git必会操作

文章目录 带你学会Git必会操作1Git的安装2.Git基本操作2.1本地仓库的创建2.2配置本地仓库 3.认识一些Git的基本概念3.1操作流程&#xff1a; 4.一些使用场景4.1添加文件场景一4.2查看git文件4.3修改文件4.4Git版本回退4.5git撤销修改 5.分支管理5.1查看分支5.2创建本地分支5.3切…

使用Docker Compose管理Java微服务

使用Docker Compose管理Java微服务 大家好&#xff0c;我是微赚淘客系统3.0的小编&#xff0c;是个冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们来探讨如何使用Docker Compose来管理Java微服务。Docker Compose是一个用于定义和运行多容器Docker应用程序…

【C++进阶】AVL树详解

文章目录 1. AVL树的概念2. AVL树结点的定义3. AVL 树的插入3.1 关于平衡因子3.2 插入代码 4. AVL 树的旋转逻辑4.1 不需要旋转4.2 左旋4.3 右旋4.4 双旋4.4.1 先右后左单旋&#xff08;RL 旋转&#xff09;4.4.2 先左后右单旋&#xff08;LR 旋转&#xff09; 4.5 完整插入代码…

web UI自动化测试 浏览器模式设置

自动化之浏览器模式设置 做selenium UI自动化测试时&#xff0c;每次都需要启动浏览器、用例运行结束后再关闭浏览器&#xff0c;浏览器启动相当地耗费时间&#xff0c;在本机运行用例的话还得放开双手&#xff0c;可以使用chrome的headless模式&#xff0c;让浏览器在后台运行…

C语言pow函数

cmath库里有pow函数&#xff0c;这个函数在图形处理方面上经常用到&#xff0c;但是如果让你自己写这个函数&#xff0c;就不一定能写出来了&#xff0c;本期文章我就带大家写pow函数 源码&#xff1a; double factorial(int n) {if (n 0) return 1;double result 1;for (i…

C语言 | Leetcode C语言题解之第301题删除无效的括号

题目&#xff1a; 题解&#xff1a; struct Next { int l, r, cl, cr; };void vec_push(char*** v, int* n, char* s) {if (!(*n & *n1)) {*v realloc(*v, sizeof(char*) * ((*n << 1) | 1));}(*v)[(*n)] s; }void dfs(const char* s, int i, struct Next next[],…