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

【Unity】YooAsset问题记录

1前言

        主要是记录一些针对YooAsset使用中的一些问题,方面后续查阅。

        无法保证100%正确。

2 问题

2.1 资源卸载问题

资源的卸载本质还是针对Bundle进行的,一个Bundle里可以包含多个资源(AB包概念)。这里对Release()、UnloadAllAssetsAsync()、TryUnloadUnusedAsset(string location)进行讨论。

Release()指句柄的释放。加载资源后返回以一个句柄,用这个句柄调用此API即可。这里释放句柄仅仅是释放了对Bundle的引用,资源本身并没有释放,比如我们加载资源并实例化了一个模型对象,那么这个模型对象并不会丢失。

UnloadAllAssetsAsync()卸载所有未使用资源。这里的资源是Bundle,未使用表示Bundle的索引计数为0。而索引计数则是需要前面的句柄Release()来释放。这么一说就很明了了。需要注意,即使资源被实例化仍然在使用,我们依旧可以句柄Release()来释放索引,但只要索引计数为0,那么Bundle就可以被卸载,即我们正在使用的资源就可以被卸载,比如上面的实例化模型例子,资源被卸载后,模型就会丢失。

TryUnloadUnusedAsset(string location)卸载某一资源。这里的资源依旧是Bundle,是输入参数表示的资源所属的Bundle。释放条件依旧是Bundle索引计数为0。比如Bundle中有两个资源被使用过,被索引,我们释放其中一个资源的索引,然后使用此API指定此资源卸载,那么会成功吗?答案是不会,因为另一个资源的索引还是存在的,那么Bundle的索引就不是0,就无法卸载。

实验:对于同一个资源,进行两次加载,获得两个句柄,则必须全部Release掉,才能正常卸载掉资源,由此可知同一资源也可进行多次索引。那么有问题,对于同一资源的加载,YooAsset内部会对其进行优化吗?【我暂时认为会优化好吧。】

2.2 文件服务器地址问题

地址一般是:{服务器地址}/{文件夹层级}/{版本号}。

可以看到最后是文件夹的名称是版本号,那么这个一定要是版本号吗,经过发现是不必要的。即使版本号设置为v1.1,但我将内部的.version文件中的版本号修改为v1.12,程序请求更新获得的版本号则是v1.12,且后续无法正常更新清单文件,而我将清单文件名称的末尾版本号改为v.1.12后,则可以正常更新清单文件。所以版本的使用需要.version文件中的版本号和清单文件名称进行配合,这才是根本所在,而我们的版本号文件夹名称仅仅是一种形式,方便我们以文件夹区分版本。我们也应该(没测试)可以将多个版本放在一个文件夹内,留一个.version文件,修改此文件中的版本号来选择更新的版本。

2.3 StreamingAssets文件夹

此文件夹中的内容主要是在打包资源时,通过配置项,来将打包的资源复制一份到这里存储。其内容可用于Host模式、Offline模式。用于Host的模式时只是作为资源寻找的一部分,因为此模式下还会再去寻找沙盒内的资源。Offline模式则只会使用此文件夹中的内容,包括清单、资源包。此文件夹中的内容不会因为网络更新而改变。

2.4 YooAssets v2.2.1版本问题

2.4.1 问题1:初始化失败

在编辑器模式下,若选择“离线模式”或“Host模式”(WebGL没有测试),则会存在有时无法初始化的问题。查找发现是“Assets\Resources\yoo\DefaultPackage\BuildinCatalog.asset”文件导致的(也可能间接导致),解决方法是执行程序前,把此文件删除,或者将此文件中的版本号修改一下与当前不同即可。此文件是根据StreamingAssets中内容进行生成的,似乎是在重复生成的时候会出这种错误。在尝试删除解决是发现在运行时,初始化前进行删除并不能解决错误,而是要运行前删除,因此设置为在Boot脚本的OnDestroy()函数中来删除(通过宏设置编辑器状态下执行,打包状态下此文件很重要,不能删除),每次运行结束时删除,这样下次运行时就是没有此文件的状态,就可以正常初始化。另外,打包状态下,没有此问题。

怀疑是生成的此文件清单内容与实际不符导致的,即StreamingAssets文件夹下内容与当前实际不符合,这个文件夹更新时并未修改内容,所以内容都是开始打包时生成的内容,更新一次后内容就过旧了。

2.4.2 问题2:清单更新失败

在更新清单时有时会更新失败,提示后点击交互按钮重新更新即可成功更新。在编辑器状态下发现是“项目名\yoo\DefaultPackage\ManifestFiles”文件夹下的文件导致的,将对应版本的清单文件删除就不会再更新失败。但后来又不报错了,不删除也不会报错,具体原因未知,这里记录下,目前问题不大。

ManifestFiles文件夹说明:这个文件夹中的文件会根据版本来存储一些清单文件,如更新过多个版本,就会存在多个版本的清单文件。

似乎理解了,若文件夹中的清单文件不存在,不会报错。版本一致、清单内容也一致则不会报错。而如果版本一致,清单内容却不一致,则会报错然后文件被删除,需要重新更新清单。(参考这里“源代码解析”的内容理解的。)

2.5版本更新清单问题

官方文档:


源代码解析

Package.UpdatePackageManifestAsync()方法解析。

  • 联机运行模式

    通过传入的清单版本,优先比对当前激活清单的版本,如果相同就直接返回成功。如果有差异就从缓存里去查找匹配的清单,如果缓存里不存在,就去远端下载并保存到沙盒里。最后加载沙盒内匹配的清单文件。


2.5.1 清单文件更新

虽然官方文档上说版本相同就直接返回,但测试发现,版本相同也会去“项目名\yoo\DefaultPackage\ManifestFiles”中寻找清单,即寻找新的清单文件。意味着本地与服务端同版本号也是可以实现正常更新的

打包后是通过生成的清单资源来记录的。编辑器模式下,虽然会读取StreamingAssets文件夹下的内容,但经过测试发现本身也有记录最新资源清单的功能,但不知道记录到哪里了。比如编辑器模式下,我们分出v1.0前和v1.0后两个版本,StreamingAssets中记录v1.0前版本,后续项目更新到v1.0后版本,然后再准备更新到v1.0前,这时候StreamingAssets中依旧是v1.0前,但更新的时候是可以确切进行资源替换的,也就是说项目此时并未依赖StreamingAssets中的内容,本身在某处是可以清楚识别自身资源情况的,然后跟新清单进行对比,更新资源。

2.5.2 版本选择

由以上内容考虑,版本相同的话就直接返回成功了,所以若在相同版本内更新是不安全的,若清单内容不变则没事,但只要有改变就是错误的,所以建议每次更新都提供新的版本。←但这句话有问题,经过测试发现版本相同也可正常更新,不过还是建议每次更新都使用新的版本,这样更好管理一些。

2.6 加载资源为空

若资源路径错误,对应资源为空,那么程序会报警告和错误,但不会影响程序正常执行。加载返回的句柄依旧存在,但句柄中资源对象为null,使用句柄实例化对象也会无效。需要注意,Resources加载若资源不存在则是直接返回null。所以整体上,他们是相似的。

2.7 更新时新资源删除了某些资源如何更新

若一个AB包中有x和y资源,场景中会实例化这两个资源,这是初始状态。后续我们又做了一个AB包,里面只有x资源,我们放到服务器上,然后热更新,那么AB包将被更新替换,场景中奖只会实例化x资源。

若AB包是分开的,比如有x包、y包里面是各自的资源,那么我们将其实例化可得到x和y资源。然后我们删除y包,进行热更新,那么最终就只能实例化出x资源。

但有个问题,就是即使热更新的时候减少了相关资源,实例化的时候也确实无法实例化出来,但热更新时并未提示下载资源。所以当我们热更减少资源时,要减少的资源究竟是被删除了(热更时资源完全替换),还是说只是被隐藏了?更新资源是只能增量更新,无法减少项目包的体积吗?【!!!!!见“资源加载模式下资源如何加载”中的说明,已经解决了。】

2.8 资源加载模式下资源如何加载

2.8.1 EditorSimulateMode

资源的读取不依靠AB包,可直接读取项目中的资源,即不需要打包。但想要读取到项目中的资源也是有条件的,需要在YooAsset的收集器配置页面保证资源处于某个收集器内才行。比如,收集器收集了一个文件夹中的资源,那么我们想加载一个新资源,只需要将新资源放到这个文件夹中即可,程序就可以正常加载这个资源了。

2.8.2 OfflinePlayMode

资源从AB包中读取。读取的是StreamingAssets文件夹下的AB包,这些AB包是在我们打包时可以选择复制过来的。

PS:离线模式下是会完全按照StreamingAssets文件夹中的相关资源来执行的,使用其清单、资源包。比如网络模式下显示了某一风格A的资源,但切回离线模式就会以此文件夹中的资源为准,若此文件夹中的资源是另一种风格B,则会显示B风格。

2.8.3 HostPlayMode

资源从AB包中读取。从网络端服务器下载这些资源。读取的应该是从两个地方来的,一个是SreamingAssets文件夹,一个是沙盒文件夹。(官方说法:YooAsset在检查更新的时候,会首先检查内置资源目录里是否存在,然后检查沙盒目录里是否存在,如果都不存在,就认为需要下载。)由此我进行了一些实验,接下来我将会说明(以下内容都是实验所得,无法保证100%正确性)。

比如有三个版本的资源,A、B、C,其中A版本资源是在构建资源时就通过配置选项进而复制到项目中的(SreamingAssets文件夹),那么接下来进行更新。若更新了B资源,则由于不存在B资源,所以会下载B资源,下载到哪里呢,这里我测试得出的结论是沙盒里。那么这时候项目就包含了A、B两种资源,即我们通过替换服务器上的资源,来更新A资源、B资源,都不会再进行下载。那么此时,我们再更新C资源,由于不存在C所以会下载C资源,并覆盖沙盒中的B资源!此时项目中有A和C资源,那么我们若再更新A资源是不会下载的,但更新B资源则会再次下载,因为其之前被C给覆盖了。至此,资源检查更新读取流程就理清楚了,还是挺重要的。

PS:这种模式下,网络端必须要有资源,因为要请求清单,并会根据清单内容来进行资源的调用。

2.8.4 WebPlayMode

在WebGL平台打包时选择此模式即可,不会进行网络请求更新,似乎需要打离线包。

2.9 开启索引地址问题

若开启索引地址,并以名称方式,那么在不同文件夹内有相同名称的资源会报错。通过关闭索引地址可以解决这个问题。另外,应该也可以把名称方式改为其他方式来解决这个问题,不过我还没有实验。

2.10 资源打包耗时问题

首先,这里只说明我目前所遇到的造成问题严重的.prefab文件。首先来说明下.prefab文件的特点,一般来说我们会导入一个模型文件,一般是.fbx文件,我们再由这个.fbx文件创建我们的.prefab文件。那么这里我们来讨论两种.prefab文件,假设此.prefab文件是一个人物,并由一个.fbx文件创建而来:

  1. .fbx是一个城市模型,里面包含了许多人物模型,而我们创建的.prefab只是其中的一个人物模型。(一号prefab)

  2. .fbx是一个人物模型,而我们创建的.prefab就是这个人物模型。(二号prefab)

那么问题来了,这里两个模型在打包时耗时是怎样?答案是:谁的.fbx文件的Mesh多,谁就耗时。一般是一号prefab耗时短,二号prefab耗时长。

结论已经在上面给出了,说下目前项目的问题。项目当中有一些prefab是一号的情况,有些prefab是二号的情况,所以导致打包时若包含了是二号情况的prefab,将导致打包不出来。内置渲染管线打包整个项目资源直接4-5个小时都不结束,迫不得已终止打包,不知道继续打会不会成功。使用脚本渲染管线打包其中一个二号情况的prefab,直接内存爆炸,打包一段时间后,结束并报错。综上所述,我们应该重视这个问题。另外,说下mesh个数问题,2768个mesh就处于一直卡住打包的状态了,所以建议控制在1000左右。

3 后记

无。

http://www.dtcms.com/a/287629.html

相关文章:

  • 深度学习-线性神经网络
  • 剧本杀小程序开发:科技赋能,重塑推理娱乐新形态
  • 大模型军备竞赛升级!Grok 4 携 “多智能体内生化” 破局,重构 AI 算力与 Agent 2.0 时代
  • 1 渗透基础
  • FOC算法六步算法 以及 Vds保护是什么
  • 石子问题(区间dp)
  • 【c++】提升用户体验:问答系统的交互优化实践——关于我用AI编写了一个聊天机器人……(12)
  • QCC系列显示交互层的自研技术突破与实践
  • 论文reading学习记录4 - weekly - 视觉端到端开创-LOAM
  • 6 STM32单片机的智能家居安防系统设计(STM32代码+手机APP设计+PCB设计+Proteus仿真)
  • VRRP-虚拟路由冗余协议
  • leetcode3_435 and 605
  • 在服务器(ECS)部署 MySQL 操作流程
  • C++控制台贪吃蛇开发:从0到1绘制游戏世界
  • Linux --进程信号
  • 2025年燃气从业人员证考试题库及答案
  • Linux——文件压缩和解压
  • 结合python面向对象编程,阐述面向对象三大特征
  • volka 可理解性输入:做家务
  • 学习C++、QT---29(QT库中QT事件的介绍和用了几个案例来对事件怎么使用的讲解)
  • lvs原理及实战部署
  • Linux内核设计与实现 - 第5章 系统调用
  • CS231n-2017 Lecture3线性分类器笔记
  • 什么是 Git 的钩子 Hooks?包括哪些内容?
  • picoCTF 2024: [[NoSQL]] Injection - Writeup
  • K8s与Helm实战:从入门到精通
  • 【杂谈】硬件工程师怎么用好AI工具做失效分析
  • 图像缩放的双线性插值算法
  • Keepalived 监听服务切换与运维指南
  • Redis常见线上问题