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;
    }
}
相关推荐
asdzx6726 分钟前
C# 操作 PDF 元数据:从属性写入到字段提取的完整流程
前端·pdf·c#
氷凌公子2 小时前
算法与UI拆分中遇到的问题及解决方式
c#·onnx·yolov26
1-1=03 小时前
C# 泛型
c#·.net·.netcore
Martina_032117 小时前
AI生成的3D模型打印后沿层纹开裂?用6步检查方向、壁厚与填充
图像处理·人工智能·数学建模·3d·自然语言处理·游戏策划·1024程序员节
Solange__1 天前
在线3D预览器、Blender和游戏引擎怎么选?按5类任务比较格式、隐私与编辑性
人工智能·游戏·3d·游戏引擎·blender·1024程序员节·关卡设计
椒颜皮皮虾྅1 天前
让文档不止于文字:DeploySharp + PP-Structure,打通版面分析与表格重建
开发语言·学习·c#·.net·cuda
peter67681 天前
unity2d游戏开发经验总结
unity
郝学胜-神的一滴1 天前
游戏设计:原型与开发 19:U3D工位布置与性格说明书
人工智能·算法·unity·unreal engine·游戏策划·游戏设计
椒颜皮皮虾྅1 天前
一套 C# 接口,解锁四类视觉任务:DeploySharp 分类、分割、关键点与旋转框实战
开发语言·分类·c#