2026.6.7 - AB包学习(1)
完成了什么
分别用三种方式加载 AB 包中的资源:
普通同步加载:最简单的用法,直接加载单个 AB 包中的资源
依赖加载:处理 AB 包之间的依赖关系,分两种写法
异步加载:运行时动态加载,避免卡顿
示例资源:一个 AB 包里包含Bullet和Cylinder两个预制体。
一、普通同步加载
LoadPath = Application.streamingAssetsPath; // 加载 AB 包文件 AssetBundle ab = AssetBundle.LoadFromFile(LoadPath + "/" + "model"); // 从 AB 包中加载资源 GameObject go = ab.LoadAsset<GameObject>("Bullet"); GameObject go2 = ab.LoadAsset<GameObject>("Cylinder"); // 实例化到场景 Instantiate(go); Instantiate(go2);关键点:
LoadFromFile从磁盘文件加载 AB 包,同步执行,会卡主线程LoadAsset<T>从已加载的 AB 包中获取指定名称的资源适合启动时加载(配合 Loading 界面)或小文件
二、依赖加载
当 AB 包之间有依赖关系时(比如model包引用了material包里的材质),需要先加载所有依赖包,否则资源会丢失材质或贴图。
写法一:加载全部依赖(简单粗暴)
// 加载主包(Manifest 包) AssetBundle abMain = AssetBundle.LoadFromFile(LoadPath + "/" + "StandaloneWindows"); // 获取 Manifest AssetBundleManifest abManifest = abMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest"); // 获取所有 AB 包名称 string[] depNames = abManifest.GetAllAssetBundles(); // 全部加载 foreach (string depName in depNames) { AssetBundle.LoadFromFile(LoadPath + "/" + depName); }适用场景:资源数量少、不在乎加载时间。
写法二:只加载指定包的依赖(推荐)
// 获取 "model" 这个包依赖了哪些包 string[] deps = abManifest.GetAllDependencies("model"); // 只加载这些依赖 foreach (string depName in deps) { AssetBundle.LoadFromFile(LoadPath + "/" + depName); }适用场景:AB 包数量多,只想加载当前需要的包及其依赖,节省内存。
两种写法的区别:
| GetAllAssetBundles | GetAllDependencies | |
|---|---|---|
| 加载范围 | 所有 AB 包 | 指定包的依赖 |
| 内存占用 | 大 | 小 |
| 适用场景 | 小项目、全量预加载 | 大项目、按需加载 |
三、异步加载
运行时加载资源,不想卡主线程,就用异步。
IEnumerator ABAsyncLoad(string path) { // 异步加载 AB 包文件 AssetBundleCreateRequest abAsync = AssetBundle.LoadFromFileAsync(path); yield return abAsync; // 等待加载完成,主线程不卡 AssetBundle bundle = abAsync.assetBundle; if (bundle == null) { Debug.LogError("Failed to find AssetBundle"); yield break; } // 从包中同步加载资源(此时包已在内存中,速度很快) GameObject prefab = bundle.LoadAsset<GameObject>("Bullet"); if (prefab != null) { Instantiate(prefab); } } // 调用 StartCoroutine(ABAsyncLoad(LoadPath + "/" + "model"));关键点:
LoadFromFileAsync返回AssetBundleCreateRequestyield return等待加载完成,不阻塞主线程AB 包加载完成后,内部资源的
LoadAsset用同步方式即可,因为文件已在内存中
什么时候用异步:
| 场景 | 推荐方式 |
|---|---|
| 启动时加载 | 同步(反正有 Loading 界面) |
| 运行时换武器、切场景 | 异步(不能卡玩家操作) |
| 加载大文件(>10MB) | 异步 |
| 加载小配置文件 | 同步 |
四、卸载
AssetBundle.UnloadAllAssetBundles(false);参数区别:
false:只卸载 AB 包本身,已加载的资源(预制体、贴图等)保留true:连同所有已加载的资源一起卸载
什么时候用:
切换场景时调用
UnloadAllAssetBundles(true)彻底清理只想释放 AB 包内存,但资源还要用,用
false
五、总结
| 加载方式 | 方法 | 特点 |
|---|---|---|
| 同步加载 | LoadFromFile | 简单,会卡主线程 |
| 异步加载 | LoadFromFileAsync | 不卡主线程,配合协程 |
| 依赖加载 | GetAllDependencies | 按需加载依赖,省内存 |
| 卸载 | UnloadAllAssetBundles | 释放 AB 包内存 |
