Unity_AssetBundle相关

AB包基础

AB(AssetBundle)是一组被 Unity 按需打包的资源集合,重点是"按标签/目录划分、运行时按需加载"。生成后会得到:

AssetBundle Browser 导入方式

  1. 打开 Package Manager :Unity 顶部菜单选择 Window → Package Manager
  2. Unity Registry 安装
    • Package source 设置为 Unity Registry
    • 在搜索框输入 AssetBundle Browser ,选择后点击 Install,等待自动集成完成。
  3. 若在官方仓库中不可用
    • 在 Package Manager 左上角点击 +,选择 Add package from git URL...
    • 输入 com.unity.assetbundlebrowser 并点击 Add 完成安装。
  • AB 包文件:真正的资源载体,按包名区分。
  • Manifest 文件:为每个 AB 自动生成,记录资源清单、依赖关系、版本号、压缩信息等,加载时用它决定先加载谁、校验是否需要更新。
  • 关键 AB 包:根清单(和输出目录同名的包),描述全部 AssetBundle 的拓扑,补充全局依赖信息。

AB包作用

  • 降低首包体积:只把核心资源放进安装包,其余在线增量下载。
  • 复用与热更新:按需更新单个包即可完成资源修复或新增内容。
  • 精细化内存管理:结合 AssetBundle.Unload 控制生命周期,避免一次性加载整套资源。
  • 跨项目复用:可被多个项目/子游戏共享,只需统一 Manifest。

AB包打包

  1. 在工程中给资源配置 AssetBundle 标签,或用自定义 Builder 脚本按目录批量设置。
  2. 打开 BuildPipeline/Addressables 等构建入口,如官方示例工具窗口,选择 Build 选项卡。
  3. 设置参数(对应截图)后点击 Build:
    • Build Target:输出目标平台,决定资源格式(示例为 Standalone Windows)。
    • Output Path :生成目录(如 AssetBundles/PC)。
    • Clear Folders:构建前清空输出目录,避免旧包残留。
    • Copy to StreamingAssets :构建后自动复制到 StreamingAssets,这样在打包 Player 时 AssetBundle 会随应用一起进入安装包,运行时可通过 Application.streamingAssetsPath 直接定位,适合离线或首包必备资源。
    • Compression :压缩模式,Chunk Based Compression (LZ4) 读写速度快、适合频繁加载,LZMA 压缩率更高但解压慢。
    • Exclude Type Information:若勾选会移除类型树信息,减少体积但会限制跨版本兼容性。
    • Force Rebuild:忽略缓存,强制重新构建所有包,适合怀疑缓存损坏时使用。
    • Ignore Type Tree Changes:即使类型树变化也复用增量缓存,可加快构建但可能导致运行时加载失败,除非对兼容性非常确定。
    • Append Hash:在输出文件名后附加 Hash,可实现 CDN 缓存刷新、版本共存。
    • Strict Mode:启用严格校验,发现未标记资源或依赖问题时会终止构建。
    • Dry Run Build:只执行模拟构建,验证配置与依赖,不产生实际文件。
  4. 构建完成后,确认 manifest 与关键 AB 包齐全,将它们连同目标包上传或放入更新服务,运行时先加载关键 manifest,再按依赖加载具体 AB。

AB包资源加载

基础 API

csharp 复制代码
// 加载 AB 包
AssetBundle bundle = AssetBundle.LoadFromFile("AB包路径/AB包名");

// 泛型方式加载资源
bundle.LoadAsset<T>("资源名");

// 指定类型加载资源
bundle.LoadAsset("资源名", typeof(GameObject));

// 同一个 AB 包不能重复加载,否则会报错

卸载

csharp 复制代码
// 卸载单个包,true 表示连同实例一起卸载
bundle.Unload(true);

// 卸载所有已加载的 AB 包
AssetBundle.UnloadAllAssetBundles(true);

异步加载

csharp 复制代码
StartCoroutine(LoadABRes("包名", "资源名"));

IEnumerator LoadABRes(string abName, string resName)
{
    AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync("包路径/包名");
    yield return request;

    GameObject prefab = request.assetBundle.LoadAsset<GameObject>(resName);
    Instantiate(prefab);
}

AB包依赖关系

如果一个包中的资源和其他包的资源有依赖关系,那么只加载一个 AB 包无法正确加载资源,需要把依赖链上的所有包都加载出来。这时就要借助"主包"(根 manifest 包)获取依赖信息。

csharp 复制代码
// 加载主包
AssetBundle mainBundle = AssetBundle.LoadFromFile("主包路径/主包名");

// 读取主包中的 manifest
AssetBundleManifest manifest = mainBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
string[] dependencies = manifest.GetAllDependencies("ab包名");

foreach (string dependency in dependencies)
{
    AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + dependency);
}

下面是一个简单的AB包资源加载的管理器(伪代码)

csharp 复制代码
// 由于 AB 包不能重复加载,用字典记录加载过的包
public Dictionary<string, AssetBundle> abDict = new Dictionary<string, AssetBundle>();
// 避免重复加载
public AssetBundle mainAB = null;
public AssetBundleManifest manifest = null;
public string Path => Application.streamingAssetsPath + "/";
public string Type
{
    get
    {
#if UNITY_IOS
        return "IOS";
#elif UNITY_ANDROID
        return "Android";
#else
        return "PC";
#endif
    }
}
public Object LoadRes(string abName, string resName)
{
    // 1. 加载主包
    if (mainAB == null)
    {
        mainAB = AssetBundle.LoadFromFile(Path + Type);   
        manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
    }
    // 2. 加载依赖文件
    string[] assetBundles = manifest.GetAllDependencies(abName);
    for (int i = 0; i < assetBundles.Length; i++)
    {
        string dependencyName = assetBundles[i];
        if (!abDict.ContainsKey(dependencyName))
        {
            AssetBundle dependencyBundle = AssetBundle.LoadFromFile(Path + dependencyName);
            abDict.Add(dependencyName, dependencyBundle);
        }
    }    
    // 3. 加载所需包
    if (!abDict.ContainsKey(abName))
    {
        AssetBundle targetBundle = AssetBundle.LoadFromFile(Path + abName);
        abDict.Add(abName, targetBundle);
    }

    // 4. 加载所需资源
    Object obj = abDict[abName].LoadAsset(resName);
    if (obj is GameObject go)
    {
        return Instantiate(go);
    }
    {
        return obj;
    }
}
相关推荐
神码编程2 小时前
【Unity】 HTFramework框架(六十八)StringEditor字符串复杂编辑器
unity·编辑器·游戏引擎·htframework
William_cl3 小时前
C# ASP.NET Controller 核心:ViewResult 实战指南(return View (model) 全解析)
开发语言·c#·asp.net
周杰伦fans3 小时前
CommunityToolkit.Mvvm(又称MVVM Toolkit) 与 MvvmLight 的核心区别
开发语言·c#·.netcore
开发游戏的老王3 小时前
UE5.6 C++项目升级UE5.7时用Rider加载项目失败的解决办法
ue5·游戏引擎·虚幻·虚幻引擎·rider·ue5.7·target.cs
TO_ZRG4 小时前
Unity-iPhone、Unity-Framework target 如何选择、@rpath报错
unity·ios·iphone
William_cl4 小时前
C# ASP.NET Controller 核心:PartialViewResult 实战指南(AJAX 局部刷新全解析)
ajax·c#·asp.net
yue0085 小时前
C# winform窗体换皮肤
c#·image类
曹牧10 小时前
C#:无法从方法组转换为objec
开发语言·c#
平行云12 小时前
World Labs & Paraverse:统一3D世界的创造与访问
3d·unity·ai·ue5·aigc·实时云渲染·云xr