谈谈我用Unity5的AssetBundle踩到的几个坑

本文分享了在Unity5中使用AssetBundle遇到的问题及解决方案,包括图集打包重复、依赖管理不当等问题,并提供了自定义图集生成方法和依赖记录技巧。

在上段时间摸索了Unity5的assetbundle用法之后,我在项目里面全面的使用起来,于是发现了一些坑,这里和大家分享一下,顺便说说我是怎样解决的。
首先是图集打包的问题。这个问题在unity5.2版本已经解决了,但在5.2之前确实是一个bug来的。具体的表现是,你把同一个图集标签的散图打包成同一个assetbundle时,这个assetbundle既包含了图集的大图,也包含了散图本身,变成了重复打包,容量暴增。这个问题困扰了我一小段时间,后来尝试着下载了个unity5.2,就没有这个问题了,图集散图打包成一个assetbundle,只会保留图集的大图作为texture2d,那些散图全部都只有sprite,没有texture2d了。
第二个问题,其实也是图集引起的。具体表现是如果你的UI(指的是UGUI)上面使用了图集,然后把UI的预设打包Assetbundle,那么就算UI依赖的图集本身已经设置了AssetName,但UI的Assetbundle本身还是会包含图集的大图来打包,又重复打包了,容量同样暴增。这个问题在5.2依然存在。
第三个问题,Unity5的Assetbundle是自动寻找需要重新打包的内容来增量打包的,这个判断有时候会不准确。具体表现是,比如刚才那些重复打包的内容,我在项目内把图集取消了,那么所有由于图集引起的问题就都不存在了,打包出去的Assetbundle就变得很小了,然后再把图集标签设置回去,再重新打包Assetbundle,居然发现有时候之前打包变小了的Assetbundle没有再变回巨大的容量,而在运行的时候也没有出错……虽然这好像是好事情,但由于是不稳定的,应该算是一种bug来的,所以不能依靠这种方法来解决问题。
第四个问题,其实不算问题,是Unity对于图片的处理方式,不过对于项目实际发布时的容量会有影响。比如你把一张只有100多k的图片放到项目里面,由于Unity会自动帮你把图片生成为Unity自身的图片格式,通过自身的设置来对图片进行压缩和保存,而导致了100多k的图片进入项目后就变成了差不多1M的容量。这其实没有什么问题的,这样做对于Unity本身来说是一种性能的优化,它可以把图片更快的转换成显卡使用的Texture。但照这个容量打包Assetbundle,会发现原本不大的图片资源,突然就变得大好几倍了。从正常的途径解决,你要么降图片质量,选择图片压缩方式,或者降图片尺寸,把图片变小。但不论你怎么做,对实际的效果还是会有影响的,特别是在ios上面看,色彩位数不够了,渐变色会变成一块一块的。

下面来说说解决的办法。
这些办法我已经实际的应用在项目里面了,暂时没发现什么问题。如果各位还有更好的方法,欢迎指教。
首先,我抛弃了通过升级unity版本来解决以上问题。最近Unity的新版本的恐怖程度应该不用我多说什么了,每次出来一个版本,就伴随着一堆新的bug出现,我怕升级完是跳过了一些坑,但又掉进新的坑里面了。
既然不能靠Unity解决,那么就只能靠自己了。
对于依赖的问题,其实我们也可以完全的不用Unity5的那套新Assetbundle机制,而使用旧版Assetbundle的自己处理依赖的方式,通过push和pop来打包依赖的。虽然这些方法被标记成已过时了,但暂时的版本还能用。不过我同样也抛弃了这样的方式,因为既然是标记成已过时方法,虽然现在还能用,但难以保证会不会在下个版本就被彻底抛弃了,这样风险有点大。
那么还是用Unity5的新机制来打包依赖吧。回头看一看,前面两个问题实际上都是由于图集引起的,所以我决定抛弃Unity的Sprite Packer,而自己写一套图集生成方法。其实我之前已经写过几次图集生成的算法了,这次稍微不同的是,我不想手下的人由于我这样的改动而对原来的制作流程有太大的变化,所以我还是直接让他们用散图的sprite来制作UI,只是在实际打包Assetbundle时,会通过我的方法,生成和Unity的Sprite Packer一样规则的图片图集。具体规则就是在图集最大尺寸可以允许的范围内,把所有散图合成一张png,如果超出了最大尺寸,再把超出的散图打包成第二张、第三张的png。但同一个图集里面的所有散图都会保存在同一个配置文件里面,所以只要加载了图集的配置文件,然后找到具体某个sprite属于哪张png,就可以按配置生成处理,而由于是同一张png的texture2D生成的sprite,他们的draw call也会是一样的。这一步反正挺成功的,我把打包和加载的方式稍微改了之后,使用者估计还不知道自己没有使用Unity的Sprite Packer。不得不说一句,面向对象就是好,边界明确,本来这样的修改会牵涉到很多的,但现在只需要小改就行了。
既然图集打包的问题解决了,那么如果UI上面用了图集又该怎么办呢?由于已经是自己生成的png作为图集,原本打的依赖肯定就不成立了,需要自己去记录一下。我的做法是在打包UI预设的时候,全部遍历查找一下有哪些是用到了sprite的,然后把sprite所属的图集名称和sprite的加载名称记录下来,然后把UI预设另存一份,把sprite去掉。再用另存的UI预设打包Assetbundle。最后在加载该UI的时候,通过配置知道那些组件上面用了哪个sprite,再在初始化的时候帮他加载回来。这一步也挺成功的,由于是完全自动化的,所以制作者根本不需要管过程,只需要按照正常流程做UI就行了。
既然前面两个问题解决了,那么第三个问题也没什么问题了。然后看第四个问题。这个问题其实官方的API上面就有解决办法,就是把图片的后缀改成bytes,这样图片就变成了TextAsset来加载,加载后再通过bytes来重新生成Texture2D。这样做了之后,在生成Texture2D的速度上是比Unity帮你保存的大容量的贴图纹理要慢一点点,但具体慢多少我没感觉出来。然后好处就是,美术给的图片是多大,那么我们打包出来的资源容量就是多大,很准确了。
然后,问题就都解决了。我的项目是把所有资源完全外部加载的,编译内部不包含任何资源,所以这个外部包的大小是很明显能看出差别的。现在项目还没有做完,资源不算特别多。在没有解决那些乱七八糟问题前,外部资源总容量有300多M,压缩了之后有100多M。解决了之后,外部资源变成只有100M左右,压缩了之后只有60多M了。由于现在还处于制作阶段,所有美术资源还没开始整理和压缩容量,相信把美术资源再整理之后,容量就会更小了。

### 如何在 Unity 中使用 YooAsset 进行资源打包 #### 工具准备 为了能够顺利使用 YooAsset,在开始之前需要完成一些准备工作。这包括安装 YooAsset 插件以及熟悉其官方文档的内容[^3]。 可以通过 Packages 清单手动安装 YooAsset,或者访问项目的 GitCode 地址获取最新版本的插件文件[^2]。确保按照官方文档中的指引配置环境设置[^5]。 --- #### 配置资源收集器 (AssetBundle Collector) YooAsset 提供了一个名为 **AssetBundle Collector** 的工具用于定义和管理资源打包规则。以下是具体操作: 1. 打开菜单栏 `Tools -> YooAsset -> Settings` 并进入编辑器设置界面。 2. 定义资源分组逻辑:通过创建 `.yar` 文件指定哪些资源被打包到同一个 AssetBundle 中。`.yar` 是一种自定义资源配置文件格式,支持灵活的路径匹配规则。 例如,可以编写如下规则: ```yaml # Example of .yar file configuration rules: - pattern: "Assets/Scenes/*.unity" bundleName: "{filename}" - pattern: "Assets/Resources/UI/*.*" bundleName: "ui/{hash:8}" ``` 上述代码表示将场景文件按名称单独打包,而 UI 资源则统一放入带有哈希值命名的 Bundle 中。 --- #### 设置构建参数 在准备好资源分组之后,下一步就是调整构建选项。打开 `Tools -> YooAsset -> Build Pipeline`,这里可以选择目标平台(如 Android、iOS 或 Standalone),并设定输出目录位置[^1]。 重要的是要勾选启用增量更新功能以便于后续热更流程更加高效[^4]。如果启用了该特性,则每次仅需重新生成那些发生更改的部分而非全部内容。 --- #### 开始构建过程 当一切就绪后点击界面上方按钮启动正式编译程序。整个过程中会经历以下几个阶段: - 收集符合条件的目标对象; - 计算它们之间的相互依赖关系; - 将最终产物导出至指定存储路径下形成可部署形式的数据结构集合。 完成后可以在终端窗口查看详细的日志记录以确认是否有任何错误或警告提示待解决。 --- #### 测试与验证 最后一步是对刚刚制作出来的包体做全面的功能性和兼容性测试。利用内置调试面板加载远程服务器上的数据来模拟真实运行环境下可能遇到的各种情况。 同时也要注意检查本地缓存机制是否正常运作,因为这对于减少网络流量消耗至关重要。 --- ### 总结 综上所述,借助强大的第三方库——YooAsset 可极大程度降低传统方式处理复杂多变需求时所面临的挑战难度。它不仅提供了直观易懂的操作界面还封装了许多底层细节使得即便是初学者也能快速掌握核心技术要点。 ```csharp // 示例脚本展示如何初始化 YooAsset 加载服务 using UnityEngine; using YooAsset; public class ResourceLoader : MonoBehaviour { private void Start() { var operation = GameEntry.Instance.StartOperation(); while (!operation.IsDone) Debug.Log($"Loading Progress:{operation.Progress}"); LoadSceneAsync("Main"); } public async void LoadSceneAsync(string sceneName) { using (var loadOp = await AsyncLoadScene(sceneName)) { if (loadOp.Status != EStatus.Succeed) throw new Exception(loadOp.ErrorInfo); Debug.Log($"{sceneName} loaded successfully!"); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值