news 2026/5/25 17:51:01

AB包相关知识

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AB包相关知识

Lua与AB包/Addressables以及YooAsset

摘自千问:

  1. Lua菜谱(逻辑):决定了菜怎么做,味道如何。因为你需要随时换菜谱(热更新),所以菜谱不能死板地印在墙上(编译进主包)。
  2. AssetBundle外卖盒(格式):你把写好的菜谱(Lua 文件)装进外卖盒里,方便运输。
  3. Addressables / YooAsset配送系统(管理)
    • 它们负责去仓库(服务器)拿外卖盒。
    • 检查盒子是不是最新的(版本管理)。
    • 把盒子送到厨房(内存),并拆开盒子把菜谱拿出来交给厨师(Lua 虚拟机)。

值得注意的是,现在除了 Lua,还有一种流行的热更方案是HybridCLR(原 ilruntime/huohuo 的替代者)。

  • 如果你用HybridCLR,你的逻辑是 C# 写的,那么 Lua 的地位就会下降,可能只用来写简单的 UI 脚本或配置文件。

AB包相关概念

热更新基本规则:

AB包浏览器插件的安装

AB包浏览器文件的安装https://blog.csdn.net/qq_36303853/article/details/148812182#t5

资源概念

C#代码不能放到AB包,因为C#是编译型语言,我们才需要脚本语言lua

Unity 编辑器通过反射,实现了对预设体上组件的动态识别、属性展示——这就是为什么Csharp脚本文件不能进AB包而组件能进AB包的原因

预制体相关概念https://blog.csdn.net/2303_80204192/article/details/157287772#t1

AB包打包流程

1.给资源划分包

如果模型上有其他主包中的资源,在打包时会构建依赖关系

2.打包页面

打包后对应文件夹就会出现

build页签中的相关属性

AB包资源加载

都是先加载AB包,再加载AB包中资源

1.AB包的同步加载:

void Start() { //加载AB包 AssetBundle ab=AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/model"); //加载资源 一种泛型,一种非泛型 GameObject go=ab.LoadAsset<GameObject>("Sphere"); GameObject go2 =ab.LoadAsset("Sphere", typeof(GameObject)) as GameObject; //实例化 Instantiate(go); }

注意:AB包不能重复加载,否则会报错!

2.AB包的异步加载(利用协程)

void Start() { // 开始协程,加载 UI 精灵 StartCoroutine(ABResLoad("head", "ui_DL_an_queding_01")); } IEnumerator ABResLoad(string ABname, string resName) { // 加载 AB 包 AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/" + ABname); yield return abcr; // 加载资源(Sprite) AssetBundleRequest abr = abcr.assetBundle.LoadAssetAsync<Sprite>(resName); yield return abr; img.sprite = abr.asset as Sprite; }

3.卸载AB包及其资源

void Update() { if (Input.GetKeyDown(KeyCode.Space)) { // 卸载所有加载的 AB 包,参数为 true 会把通过 AB 包加载的资源也卸载 AssetBundle.UnloadAllAssetBundles(false); //卸载单个资源 AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/model"); // 加载资源(泛型和非泛型两种写法) GameObject go = ab.LoadAsset<GameObject>("Sphere"); // 卸载单个 AB 包 ab.Unload(false); } }

True:AB包以及资源一起卸载 ;False:AB包卸载,资源不会卸载

AB包的依赖

如果一个模型在A包中,其材质在B包中,那么只加载A包中的模型资源会丢失材质

方法一

同时加载AB包获取模型材质和模型

方法二

这里利用主包的依赖性

//依赖包的关键知识点—利用主包 获取依赖信息 //加载主包 AssetBundle abMain = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "PC"); //加载主包中的固定文件 AssetBundleManifest abManifest = abMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest"); //从固定文件中 得到依赖信息 string[] strs = abManifest.GetAllDependencies("model"); //得到了 依赖包的名字 for (int i = 0; i < strs.Length; i++) { Debug.Log(strs[i]); }

ManiFest文件中的依赖关系如下:

缺陷:

主包依赖关系文件只能记录包与包之间的依赖关系,至于包中资源具体依赖关系是不知道的

比如A包中a资源依赖B包C包,A包中b资源需要D包E包,使用如上代码会导致加载a资源时,也会加载不需要的D包E包

GetAllDependencies

获取Manifest文件中的与对应包中的依赖关系

我这里设定一个红色球,球的模型放在model包中,材质放在materia包中

添加然后根据AB包打包流程打包情况如下

调用API

string[] strs = mainABManifest.GetAllDependencies(abName);

abName为model(即找到model包中的依赖关系并传递给strs函数),strs参数中的数据为mateia。

AB包资源加载管理器

首先需要注意:同步加载要有三种方法:泛型方法同步加载与普通参数同步加载

额外需要注意:(Lua中不支持泛型方法,所以可能会用Type形式)

同步加载

优化端:

反正三种方法都要完成如下操作:

加载对应包——查找对应包中的依赖关系——加载对应依赖包——记录加载过的包

不如将这套流程打包成一个函数在三个方法中调用

public void LoadAB(string abName) { //加载主包及主包的依赖关系 if(mainAB==null) { mainAB = AssetBundle.LoadFromFile(pathUrl + MainABName); mainABManifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest"); } //获取依赖关系 string[] strs = mainABManifest.GetAllDependencies(abName); for(int i=0;i<strs.Length;i++) { //如果AB包的依赖包没有加载过,则加载并且记录 if(!abDic.ContainsKey(strs[i])) { AssetBundle ab = AssetBundle.LoadFromFile(pathUrl + strs[i]); abDic.Add(strs[i],ab); } } //加载资源来源包 //如果AB包没有加载过,则加载并且记录 if(!abDic.ContainsKey(abName)) { AssetBundle ab = AssetBundle.LoadFromFile(pathUrl + abName); abDic.Add(abName,ab); } }

不指定类型的同步加载

public object LoadRes(string abName,string assetName) { //加载资源 LoadAB(abName); //此处设计优化了一下:在加载的同时判断是否为object类型,如果是object类型则直接实例化后返回 Object obj = abDic[abName].LoadAsset(assetName); if(obj is GameObject) { return Instantiate(obj); } else { return obj; } }

指定类型的同步加载

public object LoadRes(string abName,string assetName,System.Type type) { //加载资源 LoadAB(abName); //此处设计优化了一下:在加载的同时判断是否为object类型,如果是object类型则直接实例化后返回 Object obj = abDic[abName].LoadAsset(assetName,type); if(obj is GameObject) { return Instantiate(obj); } else { return obj; } }

外部调用该函数举例:

这里的model包中的Sphere存储是红色的球,所以会加载一个红色的球

public class ABTest : MonoBehaviour { void Start() { GameObject go = ABMgr.Instance.LoadRes("model", "Sphere",typeof(GameObject)) as GameObject; go.transform.position = Vector3.up; } }

泛型的同步加载

public T LoadRes<T>(string abName,string assetName) where T:Object { //加载资源 LoadAB(abName); //此处设计优化了一下:在加载的同时判断是否为object类型,如果是object类型则直接实例化后返回 T obj = abDic[abName].LoadAsset<T>(assetName); if(obj is GameObject) { return Instantiate(obj) as T; } else { return obj as T; } }

异步加载

这里需要注意:AB包的加载不适用异步加载,只有加载资源时才使用异步加载

与同步加载相似,也有三种加载方法

加载AB包以及AB包依赖关系与同步加载共用APi:LoadAB(abName)

不指定类型的异步加载

public void LoadResAsync(string abName,string assetName,UnityAction<Object> callback) { StartCoroutine(LoadResAsyncCoroutine(abName,assetName,callback)); } private IEnumerator LoadResAsyncCoroutine(string abName,string assetName,UnityAction<Object> callback) { //加载AB包 LoadAB(abName); //异步加载资源 AssetBundleRequest abr = abDic[abName].LoadAssetAsync(assetName); yield return abr; //此处设计优化了一下:在加载的同时判断是否为object类型,如果是object类型则直接实例化后返回 Object obj = abr.asset; if(obj is GameObject) { callback(Instantiate(obj)); } }

对传参UnityAction<T>不太了解,具体原理请看:

UnityActionhttps://blog.csdn.net/2303_80204192/article/details/157148540#t3

调用对应方法:

指定类型异步加载

public void LoadResAsync(string abName,string assetName,System.Type type,UnityAction<Object> callback) { StartCoroutine(LoadResAsyncCoroutine(abName,assetName,type,callback)); } public IEnumerator LoadResAsyncCoroutine(string abName,string assetName,System.Type type,UnityAction<Object> callback) { //加载AB包 LoadAB(abName); //异步加载资源 AssetBundleRequest abr = abDic[abName].LoadAssetAsync(assetName,type); yield return abr; //此处设计优化了一下:在加载的同时判断是否为object类型,如果是object类型则直接实例化后返回 Object obj = abr.asset; if(obj is GameObject) { callback(Instantiate(obj)); } }

根据泛型加载资源

public void LoadResAsync<T>(string abName,string assetName,UnityAction<Object> callback) where T:Object { StartCoroutine(LoadResAsyncCoroutine<T>(abName,assetName,callback)); } public IEnumerator LoadResAsyncCoroutine<T>(string abName,string assetName,UnityAction<Object> callback) where T:Object { //加载AB包 LoadAB(abName); //异步加载资源 AssetBundleRequest abr = abDic[abName].LoadAssetAsync<T>(assetName); yield return abr; //此处设计优化了一下:在加载的同时判断是否为object类型,如果是object类型则直接实例化后返回 Object obj = abr.asset; if(obj is GameObject) { callback(Instantiate(obj)); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/25 17:50:59

AI算法工程师必学的强化学习知识:这4个算法,强化学习入门必备

对于软件测试从业者而言&#xff0c;随着AI技术在测试领域的深度渗透&#xff0c;从自动化测试用例生成到智能缺陷预测&#xff0c;从测试路径优化到异常行为检测&#xff0c;强化学习正在重塑测试工作的技术框架。作为算法工程师&#xff0c;掌握强化学习基础算法不仅能帮助我…

作者头像 李华
网站建设 2026/5/25 17:45:42

终极指南:Windows微信/QQ防撤回补丁的技术实现与实战应用

终极指南&#xff1a;Windows微信/QQ防撤回补丁的技术实现与实战应用 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁&#xff08;我已经看到了&#xff0c;撤回也没用了&#xff09; 项目地址: https://gitcode…

作者头像 李华
网站建设 2026/5/25 17:44:50

在智能客服系统中集成Taotoken实现多模型路由与成本优化

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 在智能客服系统中集成Taotoken实现多模型路由与成本优化 智能客服系统是许多企业与用户交互的关键触点。随着对话需求的多样化&…

作者头像 李华
网站建设 2026/5/25 17:42:02

SingleFile:如何解决网页内容离线保存的三大痛点?

SingleFile&#xff1a;如何解决网页内容离线保存的三大痛点&#xff1f; 【免费下载链接】SingleFile Web Extension for saving a faithful copy of a complete web page in a single HTML file 项目地址: https://gitcode.com/gh_mirrors/si/SingleFile 在日常工作和…

作者头像 李华