找回密码
 立即注册
查看: 550|回复: 0

Unity的AB包详解

[复制链接]
发表于 2021-11-19 13:06 | 显示全部楼层 |阅读模式
关注公—众—号“游戏内圈”,更多免费资料和教程等着你

1.什么是资源?

在Unity的Assets目录下的文件,在游戏运行过程中需要从此目录加载并显示到屏幕上的都可以称之为Unity资源,例如模型、材质、纹理、预制体、脚本、声音、数据文档、动画切片、控制器、着色器、场景等。

2.如何管理资源?

在Unity中如果希望能非常良好地管理这些游戏资源,就必须考虑以下几点因素:

统一资源格式

制作一个Unity的资源格式标准,所有资源都采用这个相同的格式进行处理。传统格式如XML、JSON可以实现此功能,但是其安全性低、无任何加密并且打包加载速度非常慢因此并不是理想选择。

统一资源处理流程

制作(打包)资源:将游戏中的任何一类资源打包成统一的资源包格式。

使用(加载)资源:解析这个资源包并将其所包含的具体资源加载到内存中使用。

释放(卸载)资源:将不再使用的资源释放掉以节约内存空间。

Unity官方决定采用一套自主研发的完整资源解决方案称为AssetBundle,又简称AB包。

什么是AssetBundle?

AssetBundle是将资源用Unity的一种用于存储资源的压缩格式打包后的集合。它可以存储任意一种Unity引擎可以识别的资源。

Unity中的AssetBundle系统是对资源管理的一种扩展,可以动态地加载和卸载,并且大大节约了游戏包体所占空间并提高了加载效率。


创建AssetBundle

目前Unity提供了4.x与5.x两种AssetBundle资源包的创建方式。其中4.x是老版方式,相对比较麻烦,只能在打包脚本中通过纯代码的方式手工指定AB包与资源列表依赖关系。而5.x的方式做了很大改进,提供了AssetBundle创建工具,开发者可以通过该工具非常简单方便的进行编辑器操作指定AB包与资源依赖关系,可以大大提高开发效率。

然而无论使用哪种方式,开发者都需要在Unity编辑器中编写脚本来创建AB包,由于打包操作是在游戏非运行时,因此这个脚本一定能够在不运行游戏的前提下执行,Unity提供了编辑器扩展的功能来帮助开发者实现这个目的。

1.什么是编辑器扩展?

Unity编辑器扩展其实主要是指开发者通过编写C#脚本从而在Unity编辑器中添加一个新的工具菜单项来对现在的编辑器功能进行扩展或更为简单的实现管理资源的功能。这个C#脚本称之为编辑器扩展脚本。在使用编辑器扩展时需要注意以下3点:

必须在编辑器脚本中使用@MenuItem特性声明编辑器菜单项函数以用来实现相应的菜单功能。

编辑器脚本必须放在名为Editor的文件夹下。

在编辑器的菜单回调函数中实现菜单点击功能(不能是游戏运行时的功能)。


2.Unity5.x打包

(1)给每一个资源通过AB打包工具指定AB包名称(编辑器中)

(2)在打包脚本中调用public static AssetBundleManifest BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform)将标记的资源全部打入对应的AB包。

outputPath:AB包的输出路径,必须预先创建否则会打包时报错。

assetBundleOptions:为AB包构建选项,默认情况下只要选择None就可以了。

targetPlatform:为AB包的目标平台,游戏发布不同的平台此选项不同。

特别注意:

一个AB包对应两个文件,其中一个只包含资源内容本身,无后缀是一个二进制压缩文件,另外一个后缀为.manifest是对这个AB包的描述文件,其中描述了AB包中的资源列表以及依赖关系。

而在打包目录会额外生成一个与输出路径名称一样的全局AB包,它的描述文件中表示了此目录下的AB包列表以及依赖关系。


加载AssetBundle

1.加载AB包大致可以分为两个步骤:

读取AB包资源数据到程序内存。

使用AssetBundle.LoadFromFile(path),其中path是AB的路径,返回AssetBundle对象。

加载AB包中存储的具体资源对象并使用。

2.加载AB包中具体资源对象

(1)AssetBundle.LoadAsset方法,参数传递具体资源名称,不带后缀。使用泛型的方法可以自动加载并返回相应资源类型,使用不带泛型方法会返回Object,需要手动转换。

(2)AssetBundle.LoadAllAssets方法,无参一口气加载所有包中的资源到内存。使用泛型的方法那么返回的是一个特性类型的数组(前提是包中的资源都是相同数据类型),使用不带泛型的方法会返回Object数组(可以是不同类型对象)。


卸载AssetBundle

正确的做法是对于程序中确定不再使用的AssetBundle资源包,我们要及时卸载调优化内存空间来保证可以顺利加载新的资源。

Unity中只有一个负责卸载AssetBundle的方法,需要传入一个布尔类型参数,取true和false两个值含义完全不同,具体如下:

1.AssetBundle.Unload(false)

释放AssetBundle文件的内存镜像,不包含已经被加载到内存中的资源对象。

2.AssetBundle.Unload(true)

释放AssetBundle文件的内存镜像,并销毁所有资源对象,无论是否加载。



特殊资源处理

绝大多数AssetBundle资源使用上述流程和方法都可以正确处理,但是实际开发中仍然存在两类资源需要进行特殊处理。

1.脚本资源

脚本资源是一种特殊资源,脚本本身代码内容不会被打入AB包,而是只会在AB包中维护一个脚本的引用,其直接指向Assets目录下的某一个具体名称脚本,加载AB包的时候就要求在Assets目录下必须存在所有此包中资源依赖的同名脚本,否则造成所有资源的脚本丢失(物体行为逻辑丢失)。

2.场景资源

同脚本一样,场景资源也是一类极为特殊的游戏资源。在Unity中场景资源不能和其他普通资源混合打入同一个AssetBundle,必须单独打入AB包。而是当我们加载并使用AB包中的场景时(一般情况下是切换场景操作),不再需要预先将场景添加到Scens In Build场景构建列表,直接使用就可以了。


Unity4.x打包流程

不同于Unity5.x,Unity4.x没有方便的AssetBundle打包工具,只能通过在脚本中纯代码方式指定资源列表和依赖关系。

资源依赖打包与依赖加载

总结就是:如果是需要多个资源依赖的资源,建议放入公共包

1.资源的依赖打包

AssetBundle中不同的bundle的许多资源可能会同一时间依赖于相同的某个资源,例如不同模型可能会引用相同的材质,这称为AssetBundle资源之间的依赖。如果不考虑依赖关系,将两个资源分别打包到两个不同AB包中,那么它们共享的材质资源就会被打包两次,这就造成了资源的浪费。

为了避免这种浪费,需要使用AssetBundle的包依赖关系来处理。正确做法是将共享的材质资源单独打包到一个独立的AssetBundle中,让两个模型所隶属的AB包分别依赖于该独立材质AB包,这样材质资源仅会被打包一次,节省了游戏资源空间。从Unity5.x开始,系统会自动判断所有AB包的资源之间的依赖关系,不需要开发者手动处理。

2.资源的依赖加载

如果要加载一个带依赖关系的AB包,那么必须首先加载它所依赖的所有其他AB包,否则此AB包中使用Load加载的对象将会丢失依赖的资源关联。

还存在另外一种情况,当尝试加载N个带有依赖关系的AB包时,其实很难预先知道每一个AB包所依赖的其他资源列表,因此这部分依赖关系信息就需要在程序运行时动态获取。AssetBundle提供了一个名为GetAllDependencies的方法专门用于获取当前AB包所以来的资源列表,这样就可以在程序中预先加载所有依赖的AB包了。

————————————————

版权声明:本文为CSDN博主「heliocentricism」的原创文章,遵循CC 4.0 BY-SA版权协议,

原文链接:https://blog.csdn.net/heliocentricism/article/details/109209801

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-16 00:32 , Processed in 0.091653 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表