Unity AssetBundle (AB) 打包详解
AssetBundle 是 Unity 提供的一种资源打包机制,允许开发者将游戏资源(如模型、纹理、预制体等)打包成独立的文件,便于动态加载和热更新。
一、AssetBundle 基础概念
1. 什么是 AssetBundle
-
资源压缩包,包含序列化资源文件
-
可以包含任意 Unity 支持的资源类型
-
支持按需加载和卸载
-
是 Unity 热更新的基础技术
2. AssetBundle 优势
-
减小初始包体:将非必要资源分离
-
动态加载:运行时按需加载资源
-
热更新:不通过应用商店更新资源
-
资源共享:多个 AssetBundle 可以共享资源
二、AssetBundle 打包流程
1. 标记资源为 AssetBundle
在 Unity 编辑器中:
-
选择要打包的资源
-
在 Inspector 窗口底部找到 AssetBundle 设置
-
创建新的 AssetBundle 名称或选择现有名称
-
格式:
bundlename
或path/bundlename
(可添加子文件夹)
-
2. 编写打包脚本
using UnityEditor;
using System.IO;public class BuildAssetBundles
{[MenuItem("Assets/Build AssetBundles")]static void BuildAllAssetBundles(){// 创建输出目录(如果不存在)string outputPath = "Assets/AssetBundles";if (!Directory.Exists(outputPath)){Directory.CreateDirectory(outputPath);}// 开始打包BuildPipeline.BuildAssetBundles(outputPath, BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget);Debug.Log("AssetBundle 打包完成!");}
}
3. 打包选项详解
BuildAssetBundleOptions
常用选项:
选项 | 说明 |
---|---|
None | 默认选项,使用 LZMA 压缩 |
UncompressedAssetBundle | 不压缩,加载快但体积大 |
ChunkBasedCompression | 使用 LZ4 压缩,平衡体积和性能 |
DisableWriteTypeTree | 不包含类型信息,减小包体但可能不兼容 |
DeterministicAssetBundle | 确保相同内容生成相同 hash |
ForceRebuildAssetBundle | 强制重新打包所有 AssetBundle |
三、高级打包技巧
1. 依赖管理
// 获取资源依赖
string[] dependencies = AssetDatabase.GetDependencies("Assets/Prefabs/Player.prefab");// 打包时自动处理依赖
// Unity 会自动将共享资源提取到单独的 AssetBundle
2. 变体系统
// 设置带变体的 AssetBundle 名称
// 格式:bundlename.variant
// 例如:character.hd 和 character.sd// 运行时根据设备选择加载哪个变体
AssetBundle.LoadFromFile("path/to/character.hd");
3. 脚本化打包
// 更精细控制的打包方式
var builds = new AssetBundleBuild[2];// 第一个 AssetBundle
builds[0].assetBundleName = "environment";
builds[0].assetNames = new[] {"Assets/Scenes/Forest.unity","Assets/Textures/Terrain.psd"
};// 第二个 AssetBundle
builds[1].assetBundleName = "characters";
builds[1].assetNames = new[] {"Assets/Prefabs/Player.prefab","Assets/Animations/Player.controller"
};BuildPipeline.BuildAssetBundles("Assets/AssetBundles", builds, BuildAssetBundleOptions.ChunkBasedCompression,BuildTarget.StandaloneWindows);
四、AssetBundle 清单文件
打包后会生成以下重要文件:
-
AssetBundles/[YourPlatform]: 各个 AssetBundle 文件
-
AssetBundles/[YourPlatform].manifest: 平台总体清单
-
AssetBundles/[EachBundle].manifest: 每个 AssetBundle 的清单
清单文件包含:
-
资源信息
-
依赖信息
-
CRC 校验码
-
资源哈希值
五、AssetBundle 加载方式
1. 本地加载
// 同步加载
AssetBundle localAB = AssetBundle.LoadFromFile("Assets/AssetBundles/characters");
GameObject playerPrefab = localAB.LoadAsset<GameObject>("Player");// 异步加载
AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync("Assets/AssetBundles/characters");
yield return request;
AssetBundle localAB = request.assetBundle;
2. 远程加载
IEnumerator LoadFromWeb()
{string url = "http://your-server.com/characters";UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(url);yield return request.SendWebRequest();if(request.result == UnityWebRequest.Result.Success){AssetBundle remoteAB = DownloadHandlerAssetBundle.GetContent(request);GameObject enemyPrefab = remoteAB.LoadAsset<GameObject>("Enemy");}
}
3. 加载依赖
// 先加载主 AssetBundle
AssetBundle manifestAB = AssetBundle.LoadFromFile("Assets/AssetBundles/StandaloneWindows");
AssetBundleManifest manifest = manifestAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");// 获取依赖
string[] dependencies = manifest.GetAllDependencies("characters");// 加载所有依赖
foreach(string dependency in dependencies)
{AssetBundle.LoadFromFile("Assets/AssetBundles/" + dependency);
}// 然后加载主资源包
AssetBundle charactersAB = AssetBundle.LoadFromFile("Assets/AssetBundles/characters");
六、内存管理与卸载
1. 资源卸载
// 卸载单个 AssetBundle(false=只卸载AB,true=同时卸载从中加载的资源)
assetBundle.Unload(false);
// 卸载所有未使用的 AssetBundle 和资源
Resources.UnloadUnusedAssets();
2. 内存管理建议
-
及时卸载不再需要的 AssetBundle
-
避免重复加载相同 AssetBundle
-
注意资源引用关系,防止内存泄漏
-
使用
Profiler
监控内存使用情况
七、常见问题与解决方案
1. 资源丢失或引用断裂
解决方案:
-
确保所有依赖资源都正确打包
-
使用
Addressable Assets
系统替代原始 AssetBundle
2. 打包后资源变大
解决方案:
-
检查是否包含不必要资源
-
使用合适的压缩方式
-
启用
DisableWriteTypeTree
(牺牲一些兼容性)
3. 跨平台兼容性问题
解决方案:
-
为每个目标平台单独打包
-
使用
BuildTarget
参数指定正确平台
4. 热更新版本管理
解决方案:
-
实现版本比对系统
-
使用哈希值或版本号管理资源
-
提供回滚机制
八、最佳实践
-
合理划分 AssetBundle
-
按功能模块划分(角色、场景、UI等)
-
按使用频率划分(基础包、常用资源、低频资源)
-
按场景划分(每个场景一个包)
-
-
压缩策略选择
-
初始包:LZMA(高压缩率)
-
热更新:LZ4(快速随机访问)
-
-
资源冗余处理
-
将共享资源提取到公共包
-
避免资源被多个包重复包含
-
-
开发流程
-
开发期使用 Editor 模式直接加载
-
发布前切换为 AssetBundle 加载
-
自动化打包流程集成 CI/CD
-
AssetBundle 是 Unity 资源管理的强大工具,合理使用可以显著优化游戏性能并实现热更新功能。随着 Unity 发展,也可以考虑结合 Addressables 系统来获得更现代化的资源管理体验。