【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 ...
随机推荐
- Codeforces 899 F. Letters Removing (二分、树状数组)
题目链接:Letters Removing 题意: 给你一个长度为n的字符串,给出m次操作.每次操作给出一个l,r和一个字符c,要求删除字符串l到r之间所有的c. 题解: 看样例可以看出,这题最大的难 ...
- Tomcat下的Server.xml配置文件详解
自15年毕业到现在已经入行两年多了,一直以来没有深入的了解过tomcat的详细配置,只懂修改一下端口号.在网上找了些相关资料来支撑这篇文章,深入了解server.xml文件各配置的作用 <?xm ...
- 有史以来功能最全,使用最简单的excel导入/导出工具
Github地址:https://github.com/xuanbg/Utility. 还有其他一些福利,请各位园友自取. 构造方法 1.用于导出Excel文件 NpoiHelper(ExcelVer ...
- php中urldecode()和urlencode()起什么作用
urlencode()函数原理就是首先把中文字符转换为十六进制,然后在每个字符前面加一个标识符%.urldecode()函数与urlencode()函数原理相反,用于解码已编码的 URL 字符串,其原 ...
- JAVA中科学计数法转换普通计数法
今天发现数据库里汇总的数据有点大,一输出就被自动转化成科学计数法了.后来发现是转换字符串的方法有问题.如下: String a = "11234567.89"; BigDecima ...
- PHP date函数详解
在页面的最前页加上date_default_timezone_set(PRC); /*把时间调到北京时间,php5默认为格林威治标准时间*/date ()a: "am"或是 ...
- opencv学习手稿(01开篇-显示一张图片)
使用python36 源码: #-*- coding:utf-8 -*- import cv2 from PIL import Image, ImageTk import numpy as np # ...
- 企业级Docker私有仓库部署(https)
部署环境 Centos7.3 x64 docker-ce-17.06.0 docker-compose-1.15.0 Python-2.7.5(系统默认) 部署目标 使用HTTPS协议 支持Clair ...
- js中的深拷贝与浅拷贝
对象的深拷贝于浅拷贝 对于基本类型,浅拷贝过程就是对值的复制,这个过程会开辟出一个新的内存空间,将值复制到新的内存空间.而对于引用类型来书,浅拷贝过程就是对指针的复制,这个过程并没有开辟新的堆内存空间 ...
- strcpy和memcpy
切记,memcpy的头文件是memory.hstrcpy和memcpy主要有以下3方面的区别.1.复制的内容不同.strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组.整型.结构体 ...