【Unity3D技术文档翻译】第1.8篇 AssetBundles 问题及解决方法

上一章:【Unity3D技术文档翻译】第1.7篇 AssetBundles 补丁更新
本章原文所在章节:【Unity Manual】→【Working in Unity】→【Advanced Development】→【AssetBundles】→【Troubleshooting】
AssetBundles 问题及解决方法
本章节涉及一些使用 AssetBundles 的项目的常见问题。
资源重复(Asset Duplication)
从 Unity5 开始的 AssetBundle 系统会在 Object 被打包进 AssetBundle 的时候,查找所有它的依赖。这是基于资源数据库(Asset Database)实现的。依赖信息用于确定将要被包含进 AssetBundle 的 Objects 集合。
被明确指派了 AssetBundle 的 Objects 将只被打包进该 AssetBundle。一个 Object “被明确指派”的意思是:Object 的 assetBundleName 不为空。
如果 Object 没有被明确指派给一个 AssetBundle,那么该 Object 将会被包含进所有引用了该 Object 的 AssetBundles 中,无论 AssetBundle 中有一个还是多个 Objects 引用了它。
如果有两个不同的 Objects 被分别指派给两个不同的 AssetBundles,并且这两个 Objects 都对另一个 Object 有引用,那么该 Object 将被拷贝进两个 AssetBundles。重复的依赖同样会被实例化,这意味着被依赖的 Object 的两份拷贝会被认为是两个不同的 Objects,且拥有各自的 id。这将增加应用 AssetBundles 的大小。如果应用加载了这两个 AssetBundles,那么就会导致内存中加载了两份 Object 的拷贝。
这里有些方法可以解决这样的问题:
- 确保被打包进不同 AssetBundles 的 Objects 没有共同的依赖。把任何有共同依赖的 Objects 打包进同一个 AssetBundle ,避免重复依赖。
- 这个方法通常不适用于那些有很多共同依赖的项目。并且这个方法会导致作为整体的 AssetBundles 被频繁地重新构建和重新下载,造成不方便和不高效。
- 分割 AssetBundles,使得拥有共同依赖的 AssetBundles 不会同时被加载。
- 这个方法对于特定类型的项目可能有效,比如以关卡为基础的游戏。然而,这会增加项目的 AssetBundles 大小,并且增加构建的次数和加载的次数。
- 确保所有被依赖的资源被打包进它们自己的 AssetBundles。这就完全排除了重复资源的风险,但是同样的这会使情况变的复杂。应用必须追踪 AssetBundles 间的依赖关系,并且确保在调用任何 AssetBundle.LoadAsset 方法之前,正确的 AssetBundle 已经被加载好。
在 Unity5 中是通过 UnityEditor 命名空间下的 AssetDatabase 方法来追踪 Object 的依赖。正如命名空间表明的,这个方法只能在 Unity 编辑器中使用,而不是在运行时。AssetDatabase.GetDependencies 方法可被用于定位一个 Object 或者资源的所有直接依赖。注意,这些依赖可能各自也有依赖。此外,AssetImporter 方法可用于查询某个 AssetBundle 中包含的 Object。
组合使用 AssetDatabase 和 AssetImporter 的方法,就可以编写编辑器脚本,确保一个 AssetBundle 所有的直接或者间接依赖都被打包进一个或者各自的 AssetBundle 中;或者任意两个有共同依赖的 AssetBundles,被打包进同一个 AssetBundle。考虑到重复资源造成的内存开销,建议所有项目都有一个这样的脚本。
Sprite 图集重复(Sprite Atlas Duplication)
当 Unity5 中资源依赖的计算代码,和自动生成 Sprite Atlas 结合使用的时候,会出一点奇异的问题,下面的部分将描述这一点。
任何自动生成的 Sprite 图集,都会和图集生成的 Sprite Objects 一起打包到 AssetBundle 中。如果 Sprite Objects 被分配给多个 AssetBundles,那么 Sprite Atlas 就不会被打包为一个 AssetBundle,并且出现资源重复;如果 Sprite Objects 没有指明 AssetBundle,Sprite Atlas 同样不会被打包为一个 AssetBundle。
想要确保 Sprite Atlas 不重复,需要检查划分到同一个 Sprite Atlas 的 sprites (Tag 相同)要被指明为相同的 AssetBundle。
(Unity 5.2.2p3 会有额外的图集问题,在 Unity 5.2.2p4 已修复,建议用尽可能新的版本,这里不再赘述)
Android 纹理相关问题
由于 Android 生态系统严重的设备碎片化,经常需要将纹理压缩为不同的格式。所有 Android 设备都支持 ETC1 格式图片,然而 ETC1 格式不支持透明通道。如果应用不需要 OpenGL ES 2 的支持,解决问题最简洁的方法就是使用 ETC2 格式,该格式需要 OpenGL ES 3 的支持。
然而大多数应用都需要适配老旧设备,因此 ETC2 格式可能无法使用。解决这个问题的一个办法是使用 Unity5 的 AssetBundle 版本变量。(你还可以查看 Unity 安卓优化指南,来了解更多其他解决方案的细节)
使用 AssetBundle 版本变量,所有不使用 ETC1 格式压缩的纹理必须分配到只包含纹理(texture-only)的 AssetBundles 中。接着,为不支持 ETC2 格式的安卓生态系统创建合适的版本变量,使用特定的纹理压缩格式,比如:DXT5、PVRTC、ATITC。针对每一个版本变量,改变纹理的 TextureImporter 设置,使其与版本变量一致。
在运行时,使用 SystemInfo.SupportsTextureFormat 方法可以检测支持的纹理压缩格式。你可以使用这个信息,根据所支持的格式纹理,选择和加载相应的 AssetBundle 版本变量。
更多关于 Android 纹理压缩格式的信息,可以点击这里查看。
iOS 文件句柄溢出
这个问题在 Unity 5.3.2p2 就已经解决了。
(这个问题简言之就是:iOS 在加载一个 AssetBundle 时会产生一个文件句柄,iOS 的句柄数上限是255个,超过这个上限就会加载失败并报错。这里不再赘述。)
如果本文对你有帮助的话,点个赞或者评论一下吧!
下一章:【Unity3D技术文档翻译】第1.9篇 Unity AssetBundle 浏览管理工具 (终章)
【Unity3D技术文档翻译】第1.8篇 AssetBundles 问题及解决方法的更多相关文章
- 【Unity3D技术文档翻译】第1.7篇 AssetBundles 补丁更新
上一章:[Unity3D技术文档翻译]第1.6篇 使用 AssetBundle Manager 本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced ...
- 【Unity3D技术文档翻译】第1.9篇 使用 Unity AssetBundle Browser tool (AssetBundle系列完结)
上一章:[Unity3D技术文档翻译]第1.8篇 AssetBundles 问题及解决方法 本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced D ...
- 【Unity3D技术文档翻译】第1.5篇 本地使用 AssetBundles
上一章:[Unity3D技术文档翻译]第1.4篇 AssetBundle 依赖关系 本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced Devel ...
- 【Unity3D技术文档翻译】第1.3篇 创建 AssetBundles
上一章:[Unity3D技术文档翻译]第1.2篇 为打包 AssetBundles 准备资产 本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced ...
- 【Unity3D技术文档翻译】第1.6篇 使用 AssetBundle Manager
上一章:[Unity3D技术文档翻译]第1.5篇 使用 AssetBundles 本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced Develo ...
- 【Unity3D技术文档翻译】第1.4篇 AssetBundle 依赖关系
上一章:[Unity3D技术文档翻译]第1.3篇 创建 AssetBundles 本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced Develo ...
- 【Unity3D技术文档翻译】第1.0篇 AssetBundles
前言 "Unity圣典"是目前对官方文档翻译比较详细的,然而文档的最新更新日期是2013年,已经远远落后最新版本,参考意义有限.官方文档.脚本手册是学习Unity3D最直接有效的途 ...
- 【Unity3D技术文档翻译】第1.2篇 为打包 AssetBundles 准备资产
本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced Development]→[AssetBundles]→[Preparing Assets f ...
- 【Unity3D技术文档翻译】第1.1篇 AssetBundle 工作流
译者前言:本章是关于从创建到加载,再到使用 AssetBundle 的整个流程的概述.阅读本章将对 AssetBundle 的工作流程有个简单而全面的了解. 本章原文所在章节:[Unity Manua ...
随机推荐
- ADO.NET复习总结(3)--参数化SQL语句--防止sql注入式攻击
1.SQL 注入 2.使用参数化的方式,可以有效防止SQL注入,使用类parameter的实现类SqlParameter Command的属性parameters是一个参数集合. 3.举例<查询 ...
- 真正从零开始,TensorFlow详细安装入门图文教程!
本文转载地址:https://www.leiphone.com/news/201606/ORlQ7uK3TIW8xVGF.html AI这个概念好像突然就火起来了,年初大比分战胜李世石的AlphaGo ...
- oracle02
SQL语句完整结构: select from where group by having order by 今天分享的知识点:(1)分组查询 select 中非组函数的列需要在group by 进行参 ...
- mysql-innoDB-锁
在InnoDB加锁前,为什么要先start transaction innodb下锁的释放在事务提交/回滚之后,事务一旦提交/回滚之后,就会自动释放事务中的锁,innodb默认情况下autocommi ...
- JavaScript事件高级绑定
js 进行事件绑定,其中一种不常见的写法是: <div id="father" style="width: 300px; height: 200px; backgr ...
- Windows脚本修改主机名-不重启
windows通过脚本方式修改主机名的方法有很多种,下面介绍修改注册表方式的脚本. 使用方法: 1 打开cmd,假如脚本名为ModifyHostname.bat 2 执行脚本,并加入脚本参数,其中第一 ...
- SQL语句-SELECT语句
select语句 Select语句是指从现存的一个或多个表中查看满足条件的数据 Select语句常规用法: 查看表中所有数据 Select * from students; 查看所有的sid和snam ...
- IT 人士如何避免中年危机?
今天咱们不谈技术,来聊点别的. 这也可能是比学习具体技术更重要的话题 - 投资. 我把投资分成两类: 投资股票.期货.现货.黄金这类常见投资品种. 投资自己.比如看书.学习.参加培训.当然<每天 ...
- Ready!Api创建使用DataSource和DataSourceLoop的循环测试用例
step one:在testSuite(假如没有,新建一个)下新建一个testcase,并新建一个DataSource(注意:创建数据源时,一定要把request中所有的传参字段都放到数据源字段中&l ...
- Sql Server的艺术(四) SQL多表查询
表的基本连接 SQL的一个重要特性就是能通过JOIN关键词,从多个交叉表中查询.分析数据. 连接表的目的 在关系数据库中,数据表设计的一个重要原则就是要避免冗余性. 减少了冗余信息,节省了数据库存储空 ...