浅谈Unity资源异步加载和Coroutine的使用

Unity-资源异步加载 0.0 阅读详情

为了节省内存,游戏的一些资源往往需要在运行时(runtime)动态加载。如果资源本身加载比较耗时,采用同步方法会产生卡顿现象,对此的解决方法通常采用多线程或者使用引擎本身自带的异步加载方法。在Unity开发中,由于一些方法(如Resources.Load)本身不支持在其它线程调用,因此多线程的使用会受到限制;而Unity脚本API对许多加载方式都有相应的异步方法,因此我们需要对Unity异步加载方法的机制有一定的理解。此外,协同进程(Coroutine)常常和异步加载方法联合使用,这里顺便也研究一下。

1. Unity异步加载资源

Unity在runtime加载资源有Resources和AssetBundle两类方法,由于AssetBundle需要先进行打包,因此在Editor中进行开发测试阶段使用不太方便。这里介绍Resources.LoadAsync异步加载资源方法,先上代码和运行结果:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class tryLoadAsync : MonoBehaviour
{

    public static TerrainData td;
    public static GameObject terrain00;
    private ResourceRequest request;

    void Start()
    {
#if UNITY_EDITOR
        request = Resources.LoadAsync("tt/myTD00"); //调用异步加载方法
        Debug.Log("异步方法!");
#endif
    }

    void Update()
    {
        if (request != null)
        {
            if (request.isDone)
            {
                Debug.Log("异步加载完成了!");
                td = request.asset as TerrainData;
                if (!td)
                {
                    Debug.Log("加载terraindata失败!");
                }
                //创建地形
                terrain00 = Terrain.CreateTerrainGameObject(td);
                terrain00.transform.position = new Vector3(0, 0, 0);
                terrain00.GetComponent<Terrain>().Flush();

                request = null;
            }
            else
            {
                Debug.Log("已经过了一帧了!"); //异步方法至少需要一帧的时间才能生效!
            }
        }
    }
}

异步加载和同步加载的区别用另外一种概念描述就是“阻塞”。同步方法会阻塞在当前代码的执行,而其它部分(如UI)都在等着它结束调用,因此如果资源加载很耗时,那么就会出现“卡住了”的现象。异步加载则是非阻塞的,调用完异步方法后,代码继续执行,而加载工作由Unity在后台另开辟一个异步线程来进行。比如上面的代码中,在初始化Start方法中调用了Resources.LoadAsync异步方法加载一个TerrainData地形资源,该方法立即返回一个ResourceRequest类型的消息,之后继续执行下一条Debug.Log语句,而并不会等待加载的完成。

加载状态的查询有两种方法:一种是后面要介绍的yield return方式,另一种是这里采用的手动查询方式。我们在每帧运行的Update方法中通过ResourceRequest的isDone成员查询异步加载是否完成了。但是从控制台窗口的输出来看,第一帧执行的是else分支,也就是在第一帧时异步加载还没有完成。这并不是因为我们的资源过大(事实上这个TerrainData资源也很小),而是异步方法的生效至少要一帧的时间。异步加载的这个特性是十分重要的,不仅对于Resources类的方法,对于AssetBundle也一样。比如,你要在Update中查询一些游戏状态以决定是否要加载新的资源,你编写了判断条件、加载代码,这都很很棒。然后你继续编写代码想让这些资源立即生效,然而抱歉,在这一帧你的这些代码就没有任何意义了,因为无论你怎么样查询加载状态,它都会告诉你异步加载还没有成功,因为它至少有一帧的延迟微笑这种情况是值得注意的。


2. Couroutine的使用

协同进程Coroutine并不是线程,它使用yield return语句强行将代码分为两部分执行,每一帧Unity都会查询一下yield返回之前的位置是否满足条件。如果满足那么继续运行协程剩余的代码,并且至少会推迟一帧。比如下面的代码和运行结果:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using System.Threading;

public class tryCoroutine : MonoBehaviour
{

    public static TerrainData td;
    public static GameObject terrain00;

    private ResourceRequest request;
    // Use this for initialization
    void Start()
    {
#if UNITY_EDITOR
        StartCoroutine(LoadTerrain());
        Debug.Log("开始协同进程!");
#endif
    }

    IEnumerator LoadTerrain()
    {
        request = Resources.LoadAsync("tt/myTD00");
        yield return request;

        Debug.Log("异步加载完成了!");
        td = request.asset as TerrainData;
        if (!td)
        {
            Debug.Log("加载terraindata失败!");
        }
        terrain00 = Terrain.CreateTerrainGameObject(td);
        terrain00.transform.position = new Vector3(0, 0, 0);
        terrain00.GetComponent<Terrain>().Flush();
    }

    // Update is called once per frame
    void Update()
    {
        if (td == null)
            Debug.Log("等一等");
    }
}

程序实现的功能和上面一样,都是加载一个TerrainData资源并创建一个地形。该脚本创建了一个名为LoadTerrain的Coroutine,注意返回值一定是IEnumerator类型。在第一次运行至yield return语句时,程序返回,执行该帧的Update方法;在下一帧,由于异步加载完成,程序回到yield return的位置,继续执行这个Coroutine剩余的代码。可见,Coroutine并不是一个线程,它仍然运行在主线程中。


参考文献:

1. AssetBundle官方教程:https://unity3d.com/cn/learn/tutorials/topics/best-practices/guide-assetbundles-and-resources

2. Unity Script API:https://docs.unity3d.com/ScriptReference/index.html

Unity手游开发:异步加载 目前游戏的资源管理使用的是Addressables,仅支持异步加载。所以目前游戏内全部使用异步加载方式进行所有资源的加载。将数据存储、资源和网络异步初始化、界面逻辑表现进行分离,更条理清晰。2. 优化多个需次序进行的异步加载代码,避免“回调地狱”。展示顺序的异步加载方案,避免“回调地狱”。展示资源加载和网络请求同时异步操作示例。1. 资源加载和网络请求同时进行。展示单个资源加载过程。展示批量资源加载过程。 阅读详情

相关推荐

大模型推理中Prefill与Decode、KV Cache三者说明

Prefill 阶段对输入 Prompt 并行编码,一次性构建KV Cache,属于计算密集型任务。Decode 阶段逐 token 迭代生成,复用KV Cache避免重复计算,属于显存带宽密集型任务。KV Cache是自回归推理的核心基石,用显存换时间,实现两阶段衔接与高效生成。PD 分离通过任务解耦、异构硬件、异步调度、独立批处理,解决传统一体化推理的资源冲突与利用率低下问题,是当前云端大模型推理服务的主流工程优化方向。

a486259的博客 1489

Unity性能优化实战:从内存、渲染到CPU逻辑的全链路调优指南

在游戏与应用开发中,性能优化是确保用户体验流畅、应用稳定的核心技术环节。其核心原理在于对有限硬件资源(如CPU、GPU、内存)的高效管理与合理分配,旨在消除卡顿、降低功耗并提升响应速度。这项技术的价值在于直接决定了产品的可玩性、留存率与市场竞争力,尤其在移动端等资源受限平台至关重要。常见的应用场景包括高负载游戏场景渲染、复杂UI交互以及需要长时间运行的应用。本文将聚焦于Unity引擎,深入探讨如何通过系统性的性能分析、内存管理(如对象池与GC优化)、渲染效率提升(如合批与过度绘制控制)以及CPU逻辑优化(如

weixin_33788244的博客 452

LTspice进阶技巧-031.一键加密仿真模型:LTspice Encrypt Tool实战指南

本文详细介绍了LTspice Encrypt Tool的使用方法,帮助工程师一键加密LTspice仿真模型,保护知识产权。通过图形化界面简化操作流程,支持批量加密和兼容性处理,适用于电路设计中的模型保护需求。

weixin_28304023的博客 202

Unity中资源异步加载

本篇博客主要介绍了Unity中资源异步加载的技术原理和实现方法,并结合代码和注释进行解释和演示。异步加载在游戏开发中有着广泛的应用场景,如场景异步加载、资源预加载、多语言本地化等。在开发过程中,根据实际情况选择合适的异步加载方式能够大大提高游戏的效率和用户体验。

Asklyw的博客 4168

CodeBuddy 接入 MCP,一键生成网站!

2024 年 11 月,Anthropic 公司搞了个挺有意思的新玩意 - Model Context Protocol(模型上下文协议)简称为 MCP 协议。简单来说,它就是给 AI 和各类工具数据之间搭了个标准化的”桥梁”,让开发者不用再为对接问题头疼了。mcp.so如下图所示,这是 mcp.so 网站中的 MCP Server。使用百度/高德地图分析旅线计算时间接 Puppeteer 自动操作网页使用 Github/Gitlab 让大模型接管代码仓库。

悟空聊架构的专栏 1946

杰理JL701N V142的SDK实现双备份自定义OTA教程和代码分享

摘要 本文档详细介绍了基于JL701N SDK的UART OTA升级功能开发方案。该方案采用双备份(Dual Bank)机制,通过串口实现安全可靠的固件远程更新。核心特性包括:1) 双备份升级机制确保升级失败可回滚;2) CRC-16/XMODEM校验保障数据完整性;3) 灵活的传输控制,支持自定义波特率和数据包大小。文档提供了完整的系统架构、API接口说明、通信协议规范以及移植指南,适用于生产烧录、现场升级等多种场景。配套Python升级工具简化了升级流程,使开发人员能够快速实现固件更新功能。

qq_42014563的博客 276

Unity--异步加载资源

Unity--异步加载资源

qq_40669895的博客 3637

PyTorch实战(19)——变分自编码器(Variational Autoencoder,VAE)

变分自编码器 (Variational Autoencoder, VAE) 是一种结合了自编码器和概率建模的生成模型,通过编码器将输入数据映射到潜在空间中的概率分布,并通过解码器将从潜在空间采样得到的潜在变量映射回原始数据空间,实现了数据的生成和特征学习。本节中,将介绍变分自编码器的基本概念,并使用 PyTorch 实现变分自编码器生成新图像。

盼小辉丶的博客 2898

Unity资源处理机制(Assets/WWW/AssetBundle/...)读取和加载资源方式详解

Unity资源机制 1、概述       本文意在阐述Unity资源机制相关的信息,以及一些关于个人的理解与试验结果。另外还会提及一些因机制问题可能会出现的异常以及处理建议。大部分机制信息来源于官方文档,另外为自我验证后的结果。   2、资源 概述       Unity必须通过导入将所支持的资源序列化,生成AssetComponents后,才能被Unity使用。以下是Unity对As

天生爱赞美的博客 5万+

NOC总线架构拓扑介绍

在开篇里,我们对芯片PPA有了初步的认识。下面,让我们从访存这个简单的问题开始展开介绍芯片基础概念。CPU是怎样访问内存的?简单的答案是,CPU执行一条访存指令,把读写请求发往内存管理单元。内存管理单元进行虚实转换,把命令发往总线。总线把命令传递给内存控制器,内存控制器再次翻译地址,对相应内存颗粒进行存取。之后,读取的数据或者写入确认按照原路返回。再复杂些,当中插入多级缓存,在每一层缓存都未命中的情况下,访问才会最终达到内存颗粒。

元直的博客 5296

Java与OSG的梦幻联动:深入编译OpenSceneGraph的Java JNI桥梁,开启3D视觉盛宴的奇幻之旅

🔥关注墨瑾轩,带你探索编程的奥秘!🚀🔥超萌技术攻略,轻松晋级编程高手🚀🔥技术宝库已备好,就等你来挖掘🚀🔥订阅墨瑾轩,智趣学习不孤单🚀🔥即刻启航,编程之旅更有趣🚀在编译OpenSceneGraph (OSG) 的Java版本时,首先需要了解OSG本身是一个主要用于3D图形和视觉仿真的开源库,它主要支持C++。然而,OSG 也支持通过JNI(Java Native Interface)与Java集成,这允许Java程序调用OSG的C++库。

java专栏 870

Unity Resources.LoadAsync 优雅的写法

传统写法中 Resources.LoadAsync("path"),保存回调ResourceRequest 开启一个协程或者定时器,每帧去判断一下 ResourceRequest.isDone是否完成,这样每写一句Resources.LoadAsync就得新增一个定时器,如果使用Resources.Load同步加载很大预制体时会卡顿掉帧,所以我们的程序员宗旨就是能躺着绝不站着。1、减少后续繁琐的代码,减少重复代码,使用异步编程方式,一眼了然,优雅实在是太优雅了。

不残血不上 4477

[PCIE5.0] 2.2.8.3 Error Signaling Messages

错误信号消息用于在 PCI Express 设备之间传递错误信息,帮助系统发现并报告错误。每当发生某种错误时,检测到该错误的设备会通过发送这些消息来通知系统。• 没有数据负载:这些错误信号消息不包含任何数据(即 TLP Type 是 Msg),它们仅用于错误报告。• 长度字段保留:在这些消息中,长度字段是保留的,不使用。• 功能号(Function Number)字段:这个字段标识哪个设备发生了错误。

系统固件工程师 292

Unity实现异步的三种方法

因为工作时用到了UniTask,所以就简单比较了下在Unity在实现异步时的三种方法。

和产品battle的秃头程序 1892

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

【脚本】Unity异步加载AsyncLoad场景进度条显示

Unity异步加载AsyncLoad场景进度条显示

weixin_42565127的博客 665

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Unity resource 资源加载

使用Resources.Load或者Resources.LoadAll加载时,路径是从Resources文件夹里面的文件夹开始的,例如Resources文件夹里有一个Audio文件夹,Audio文件夹里面也有一个Music文件夹,Music文件夹有一个叫做Song的.mp3文件,则路径是"Audio/Music/Song"同步加载Resources文件夹中指定路径的文件夹中的指定类型的所有资源,包括其中子孙文件夹中的该类型的所有资源,然后返回到一个Object[]型数组。

weixin_45223588的博客 2210

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【收藏】Unity异步编程完全指南

本文将探讨 Unity 中异步编程的主要方式:讨论优缺点,展示代码示例,并展示每个方法的实际应用场景。对于新手来说,这是一份绝佳的入门指南,对于经验丰富的工程师来说,它也是一份可靠的资源!游戏开发中的一些任务不是同步的,而是异步的。这意味着它们不是在游戏代码中线性执行的。一些异步任务可能需要相当长的时间才能完成,而另一些则与密集计算相关。一些最常见的异步游戏任务如下:执行网络请求加载场景、资源和其他资产读取和写入文件人工智能决策长动画序列处理大量数据路径查找。

2401_82584055的博客 3230

Unity 场景加载和资源加载

一个游戏往往都是由很多场景组成的,例如会有主界面场景、战斗场景…等,不同的场景也是由若干的资源组合而成,在游戏的制作过程中,场景和资源的加载是不可或缺的。不管是场景还是资源都会涉及到加载的问题,在什么时候进行场景或资源的加载?场景的加载和资源的加载如何区分?加载时是使用同步的方式还是异步的方式?

ProSWhite的博客 4344

unity异步加载与同步加载

异步加载则是指在加载资源时,程序不会等待资源加载完毕后再继续执行下面的代码,而是在后台继续执行其他代码。

u011146831的博客 827

Unity 的完整异步编程入门

Unity 的完整异步编程入门

小云同志你好的博客 806

2021-05-27 Unity Resources.LoadAsync使用

Unity Resources.LoadAsync使用 1、StartCoroutine(函数名)开启一个协程 2、返回值为IEnumerator的函数,函数中有yieldreturn类型返回值,当yieldreturn执行后,才会执行yieldreturn以后的代码块 3、Resources.LoadAsync(资源路径) 异步加载的使用 返回值为ResourceRequest asset 被加载的资源 isDone 加载是否完成,bool类型 ...

qq_41194189的博客 4576

Unity基础学习(九)Resources资源同步与异步加载

本文简单介绍了Unity中的资源管理

FAREWELL00075的博客 2453

Unity——异步方法

异步方法和同步方法的区别 同步方法: 方法中逻辑执行完毕后,再继续执行后面的方法 异步方法: 方法中逻辑可能还没有执行完毕,就继续执行后面的内容 异步方法的本质: 往往异步方法当中都会使用多线程执行某部分逻辑 因为我们不需要等待方法中逻辑执行完毕就可以继续执行下面的逻辑了注:unity中的协同程序中的某些异步方法,有的使用的是多线程有的使用的是迭代

m0_51743362的博客 6713

Unity的‘异步‘操作

Unity的异步

leikang111的博客 1027

unity3d————Resources异步加载

异步加载:通过新开线程进行资源加载,避免主线程卡顿。完成事件监听:写法简单,但只能在资源加载结束后进行处理。协程异步加载:允许在加载资源的同时处理其他逻辑,写法相对复杂。注意:异步加载不能马上得到加载的资源,需要等待加载完成。

2401_82978699的博客 1411

Unity学习笔记 关于Unity和C#的异步操作详解(协程&线程)

关于Unity和C#的异步操作详解(协程&线程)

Lawa0592的博客 6782
上一篇: Unity5.6大规模地形—地形资源的创建(2)
下一篇: Unity5.6大规模地形—地形资源构建(3)
fcauto2012
博客等级 码龄11年 59粉丝 18原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值