浅谈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. 资源加载和网络请求同时进行。展示单个资源加载过程。展示批量资源加载过程。 阅读详情

相关推荐

1.Fay-UE5数字人工程导入(UE数字人系统教程)

ue5数字人系列教程(含源文件工程)

1万+

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

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

weixin_33788244的博客 452

从零搭建基于OpenSpec的现代化UI自动化测试框架实战指南

UI自动化测试是软件质量保障的关键环节,其核心在于通过脚本模拟用户操作,对Web应用界面进行功能验证。其原理在于利用浏览器驱动工具(如Selenium、Playwright)提供的API,实现对页面元素的定位、交互与断言。一个设计良好的自动化框架能显著提升测试脚本的可维护性、可读性和执行稳定性,从而在持续集成、回归测试等场景中发挥巨大价值。本文聚焦于如何构建一个现代化的UI测试框架,通过整合OpenSpec架构规范、Pytest测试引擎与Playwright浏览器自动化工具,形成清晰的页面对象模型(POM)

weixin_28836989的博客 286

Unity中资源异步加载

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

Asklyw的博客 4168

BSD盲区检测系统性能要求及试验方法

盲区监测系统BSD通过安装在车辆后方的两颗毫米波雷达实时监测驾驶员视野盲区,当发现视野盲区内出现其它道路使用者时,通过左右后视镜上的警示灯向驾驶员发出报警。

未知艺术家的博客 2359

Python爬虫实战:高效爬取中国版权登记数据

本文将详细介绍如何使用Python最新技术栈构建一个高效、稳定的中国版权登记数据爬虫系统。我们将使用Playwright+Asyncio实现无头浏览器自动化,结合Redis分布式任务队列和MongoDB数据存储,打造一个能够应对反爬机制的企业级数据采集方案。文章包含完整代码实现、性能优化技巧以及法律合规建议,帮助开发者快速掌握大规模数据采集的核心技术。本文详细介绍了2024年使用Python最新技术栈构建中国版权登记数据爬虫的完整方案。基于Playwright的无头浏览器自动化。

2201_76125261的博客 1899

Unity--异步加载资源

Unity--异步加载资源

qq_40669895的博客 3637

大数据分析实验,包含五个子实验:wordCount实验,PageRank实验,关系挖掘实验,k-means算法,推荐系统算法。

大数据分析实验,包含五个子实验:wordCount实验,PageRank实验,关系挖掘实验,k-means算法,推荐系统算法。

805

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

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

天生爱赞美的博客 5万+

Asterisk中MixMonitor之支持接通后录音

一、概述 当我们使用开源的IPPBX(比如Elastix-2.5/4.0或者ISSABEL-4.0/FreePBX)的时候Outbound和Inbound路由(RingGroup/FollowMe)中有一个Call Recording选项,其值包括:Allow、Record immediately、Record On Answer和Nerver。当选择为Record On Answer,其实就是MixMonitor自带一个b选项。 尽管Asterisk自带的MixMoni...

宽简厚重—博约 1156

蓝牙攻防实战:蓝牙技术详解

蓝牙作为轻量级、低功耗的无线通信技术,其设计兼顾了效率与灵活性,但也留下了诸多安全隐患。随着物联网设备的爆发式增长,蓝牙的攻击面也在不断扩大。理解其底层通信机制、协议栈结构以及配对加密逻辑,是提升无线安全防护能力的关键。

idlecloud0105的博客 740

Unity Resources.LoadAsync 优雅的写法

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

不残血不上 4477

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Unity实现异步的三种方法

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

和产品battle的秃头程序 1892

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

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

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

weixin_42565127的博客 665

Unity resource 资源加载

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

weixin_45223588的博客 2210

【收藏】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、付费专栏及课程。

余额充值