assetbundle c# Unity中AB包详解(超详细,特性,打包,加载,管理器)

  • admin
  • 2025-12-04 20:55:43

Unity中的AssetBundle详解

AssetBundle的概念

AssetBundle又称AB包,是Unity提供的一种用于存储资源的资源压缩包。

Unity中的AssetBundle系统是对资源管理的一种扩展,通过将资源分布在不同的AB包中可以最大程度地减少运行时的内存压力,可以动态地加载和卸载AB包,继而有选择地加载内容。

AssetBundle的优势

AB包存储位置自定义,继而可放入可读可写的路径下便于实现热更新 AB包自定义压缩方式,可以选择不压缩或选择LZMA和LZ4等压缩方式,减小包的大小,更快的进行网络传输。 资源可分布在不同的AB包中,最大程度减少运行时的内存压力, 可做到即用即加载,有选择的加载需要的内容。 AB包支持后期进行动态更新,显著减小初始安装包的大小,非核心资源以AB包形式上传服务器,后期运行时动态加载,提高用户体验。

AssetBundle和Resources的比较

AssetBundleResources资源可分布在多个包中所有资源打包成一个大包存储位置自定义灵活必须存放在Resources目录下压缩方式灵活(LZMA,LZ4)资源全部会压缩成二进制支持后期进行动态更新打包后资源只读无法动态更改

AssetBundle的特性

AB包可以存储绝大部分Unity资源但无法直接存储C#脚本,所以代码的热更新需要使用Lua或者存储编译后的DLL文件。 AB包不能重复进行加载,当AB包已经加载进内存后必须卸载后才能重新加载。 多个资源分布在不同的AB包可能会出现一个预制体的贴图等部分资源不在同一个包下,直接加载会出现部分资源丢失的情况,即AB包之间是存在依赖关系的,在加载当前AB包时需要一并加载其所依赖的包。 打包完成后,会自动生成一个主包(主包名称随平台不同而不同),主包的manifest下会存储有版本号、校验码(CRC)、所有其它包的相关信息(名称、依赖关系)

AssetBundle全打包流程

本次主要介绍Unity官方提供的AB包管理插件AssetBundle Browser 进行打包

1、AssetBundleBrowser插件的获取

Unity 2019版本可以直接在Windows —> PackageManager里面找到此插件并直接安装 2020版本之后或其它版本可能在1方法中找不到此插件,可以通过去github搜索下载压缩包,下载地址https://github.com/Unity-Technologies/AssetBundles-Browser

将下载后的安装包解压到Unity工程的Packages文件夹下 (一定要解压)

2、AssetBundleBrowser面板的使用

正确获取到并安装完插件后,通过 Windows ----> AssetBundle Browser下打开AB包管理面板 一共有三个面板 Configure面板 :能查看当前AB包及其内部资源的基本情况(大小,资源,依赖情况等) Build面板:负责AssetBundle打包的相关设置 按Build即可进行打包 三种压缩方式

NoCompression:不压缩,解压快,包较大,不建议使用。LZMA: 压缩最小,解压慢,用一个资源要解压包下所有资源。LZ4: 压缩稍大,解压快,用什么解压什么,内存占用低,更建议使用。 一般需要进行更改的设置即为图中勾选的相关选项设置。 Inspect面板:主要用来查看已经打包后的AB包文件的一些详细情况(大小,资源路径等)

3、设置资源所属的AssetBundle包

在需要打包的资源的Inspector面板下方即可选择其应放在哪个AB包下,也可通过New新建AB包将资源放入,放入后再次Build打包即可将此资源打入相应的AB包中。

AssetBundle管理器

​ 利用AssetBundleBrowser可以轻松实现AB包的打包工作,更重要的是如何将AB包中的资源加载出来并使用它们,Unity已经提供了一组API能够实现AB包的加载和资源的加载。

AB包管理器的主要需求:加载指定AB包下的指定资源,基本步骤如下:

加载资源所在AB包及其的所有依赖包(根据主包的manifest信息找依赖包名称)从AB包中加载指定的资源(根据名称,类型)不再使用时卸载已经加载了的AB包

主要相关API

//AB包加载所需相关API

//1. 根据路径进行加载AB包 注意AB包不能重复加载

AssetBundle ab = AssetBundle.LoadFromFile(path);

//2. 加载ab包下指定名称和类型的资源

T obj = ab.LoadAsset(ResourceName); //泛型加载

Object obj = ab.LoadAsset(ResourceName); //非泛型加载 后续使用时需强转类型

Object obj = ab.LoadAsset(ResourceName,Type); //参数指明资源类型 防止重名

T obj = ab.LoadAssetAsync(resName); //异步泛型加载

Object obj = ab.LoadAssetAsync(resName); //异步非泛型加载

Object obj = ab.LoadAssetAsync(resName,Type); //参数指明资源类型 防止重名

//3. 卸载ab包 bool参数代表是否一并删除已经从此AB包中加载进场景的资源(一般为false)

ab.UnLoad(false); //卸载单个ab包

AssetBundle.UnloadAllAssetBundles(false); //卸载所有AB包

下面是AB包管理器的详细代码和注释,里面涉及到的单例模式内容后面会简单进行介绍。

ABManager.cs

using System;

using System.Net.Mime;

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

namespace Common

{

///

/// AB包管理器 全局唯一 使用单例模式

///

public class ABManager : MonoSingleton

{

//AB包缓存---解决AB包无法重复加载的问题 也有利于提高效率。

private Dictionary abCache;

private AssetBundle mainAB = null; //主包

private AssetBundleManifest mainManifest = null; //主包中配置文件---用以获取依赖包

//各个平台下的基础路径 --- 利用宏判断当前平台下的streamingAssets路径

private string basePath { get

{

//使用StreamingAssets路径注意AB包打包时 勾选copy to streamingAssets

#if UNITY_EDITOR || UNITY_STANDALONE

return Application.dataPath + "/StreamingAssets/";

#elif UNITY_IPHONE

return Application.dataPath + "/Raw/";

#elif UNITY_ANDROID

return Application.dataPath + "!/assets/";

#endif

}

}

//各个平台下的主包名称 --- 用以加载主包获取依赖信息

private string mainABName

{

get

{

#if UNITY_EDITOR || UNITY_STANDALONE

return "StandaloneWindows";

#elif UNITY_IPHONE

return "IOS";

#elif UNITY_ANDROID

return "Android";

#endif

}

}

//继承了单例模式提供的初始化函数

protected override void Init()

{

base.Init();

//初始化字典

abCache = new Dictionary();

}

//加载AB包

private AssetBundle LoadABPackage(string abName)

{

AssetBundle ab;

//加载ab包,需一并加载其依赖包。

if (mainAB == null)

{

//根据各个平台下的基础路径和主包名加载主包

mainAB = AssetBundle.LoadFromFile(basePath + mainABName);

//获取主包下的AssetBundleManifest资源文件(存有依赖信息)

mainManifest = mainAB.LoadAsset("AssetBundleManifest");

}

//根据manifest获取所有依赖包的名称 固定API

string[] dependencies = mainManifest.GetAllDependencies(abName);

//循环加载所有依赖包

for (int i = 0; i < dependencies.Length; i++)

{

//如果不在缓存则加入

if (!abCache.ContainsKey(dependencies[i]))

{

//根据依赖包名称进行加载

ab = AssetBundle.LoadFromFile(basePath + dependencies[i]);

//注意添加进缓存 防止重复加载AB包

abCache.Add(dependencies[i], ab);

}

}

//加载目标包 -- 同理注意缓存问题

if (abCache.ContainsKey(abName)) return abCache[abName];

else

{

ab = AssetBundle.LoadFromFile(basePath + abName);

abCache.Add(abName, ab);

return ab;

}

}

//==================三种资源同步加载方式==================

//提供多种调用方式 便于其它语言的调用(Lua对泛型支持不好)

#region 同步加载的三个重载

///

/// 同步加载资源---泛型加载 简单直观 无需显示转换

///

/// ab包的名称

/// 资源名称

public T LoadResource(string abName,string resName)where T:Object

{

//加载目标包

AssetBundle ab = LoadABPackage(abName);

//返回资源

return ab.LoadAsset(resName);

}

//不指定类型 有重名情况下不建议使用 使用时需显示转换类型

public Object LoadResource(string abName,string resName)

{

//加载目标包

AssetBundle ab = LoadABPackage(abName);

//返回资源

return ab.LoadAsset(resName);

}

//利用参数传递类型,适合对泛型不支持的语言调用,使用时需强转类型

public Object LoadResource(string abName, string resName,System.Type type)

{

//加载目标包

AssetBundle ab = LoadABPackage(abName);

//返回资源

return ab.LoadAsset(resName,type);

}

#endregion

//================三种资源异步加载方式======================

///

/// 提供异步加载----注意 这里加载AB包是同步加载,只是加载资源是异步

///

/// ab包名称

/// 资源名称

public void LoadResourceAsync(string abName,string resName, System.Action finishLoadObjectHandler)

{

AssetBundle ab = LoadABPackage(abName);

//开启协程 提供资源加载成功后的委托

StartCoroutine(LoadRes(ab,resName,finishLoadObjectHandler));

}

private IEnumerator LoadRes(AssetBundle ab,string resName, System.Action finishLoadObjectHandler)

{

if (ab == null) yield break;

//异步加载资源API

AssetBundleRequest abr = ab.LoadAssetAsync(resName);

yield return abr;

//委托调用处理逻辑

finishLoadObjectHandler(abr.asset);

}

//根据Type异步加载资源

public void LoadResourceAsync(string abName, string resName,System.Type type, System.Action finishLoadObjectHandler)

{

AssetBundle ab = LoadABPackage(abName);

StartCoroutine(LoadRes(ab, resName,type, finishLoadObjectHandler));

}

private IEnumerator LoadRes(AssetBundle ab, string resName,System.Type type, System.Action finishLoadObjectHandler)

{

if (ab == null) yield break;

AssetBundleRequest abr = ab.LoadAssetAsync(resName,type);

yield return abr;

//委托调用处理逻辑

finishLoadObjectHandler(abr.asset);

}

//泛型加载

public void LoadResourceAsync(string abName, string resName, System.Action finishLoadObjectHandler)where T:Object

{

AssetBundle ab = LoadABPackage(abName);

StartCoroutine(LoadRes(ab, resName, finishLoadObjectHandler));

}

private IEnumerator LoadRes(AssetBundle ab, string resName, System.Action finishLoadObjectHandler)where T:Object

{

if (ab == null) yield break;

AssetBundleRequest abr = ab.LoadAssetAsync(resName);

yield return abr;

//委托调用处理逻辑

finishLoadObjectHandler(abr.asset as T);

}

//====================AB包的两种卸载方式=================

//单个包卸载

public void UnLoad(string abName)

{

if(abCache.ContainsKey(abName))

{

abCache[abName].Unload(false);

//注意缓存需一并移除

abCache.Remove(abName);

}

}

//所有包卸载

public void UnLoadAll()

{

AssetBundle.UnloadAllAssetBundles(false);

//注意清空缓存

abCache.Clear();

mainAB = null;

mainManifest = null;

}

}

}

上面管理器继承的脚本单例类如下

MonoSingleton.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

namespace Common

{

///

///脚本单例类,负责为唯一脚本创建实例

///

public class MonoSingleton : MonoBehaviour where T:MonoSingleton //注意此约束为T必须为其本身或子类

{

/*

相较于直接在需要唯一创建的脚本中创建实例,Awake初始化的过程需要解决的问题

1.代码重复

2.在Awake里面初始化,其它脚本在Awake中调用其可能会为Null的异常情况

*/

//解决1:使用泛型创建实例 解决2:使用按需加载(即有其它脚本调用时在get中加载)

private static T instance; //创建私有对象记录取值,可只赋值一次避免多次赋值

public static T Instance

{

//实现按需加载

get

{

//当已经赋值,则直接返回即可

if (instance != null) return instance;

instance = FindObjectOfType();

//为了防止脚本还未挂到物体上,找不到的异常情况,可以自行创建空物体挂上去

if (instance == null)

{

//如果创建对象,则会在创建时调用其身上脚本的Awake即调用T的Awake(T的Awake实际上是继承的父类的)

//所以此时无需为instance赋值,其会在Awake中赋值,自然也会初始化所以无需init()

/*instance = */

new GameObject("Singleton of "+typeof(T)).AddComponent();

}

else instance.Init(); //保证Init只执行一次

return instance;

}

}

private void Awake()

{

//若无其它脚本在Awake中调用此实例,则可在Awake中自行初始化instance

instance = this as T;

//初始化

Init();

}

//子类对成员进行初始化如果放在Awake里仍会出现Null问题所以自行制作一个init函数解决(可用可不用)

protected virtual void Init()

{

}

}

}

除了上面的脚本单例类 单例模式还有另外两种无需继承MonoBehaviour的纯C#单例模式 有兴趣的读者可自行了解 单例模式下的饿汉和懒汉模式。

查看原文

赞赏

本文由 用户 于 2025-08-18 发布在 夸智网,如有疑问,请联系我们。

本文链接:https://www.kuazhi.com/post/312758.html

0赞

上一篇 没有了

下一篇 没有了

相关文章

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之QRCode组件

网络 运维 在外远程控制我的世界服务器 - MCSM面板【端口映射】

测试工具 ApiPost/Postman 传参赋值详解

缓存 数据库 中间件 C/C++后端开发 熬夜万字肝爆Redis知识总结,全网最全

开发环境和测试环境共用Eureka

网络协议 网络 java HTTP协议初见/Fiddler抓包工具使用(HTTP协议1)

Linux工具——yum和vim

数据仓库 etl kettle下载百度网盘地址&含入门教程1(表间数据传输)

发表评论取消回复

0赞

微信 新浪微博 QQ空间 QQ

热门文章 下载柚子快报填写官方注册邀请码778899 2024-09-26 电脑副业赚钱的路子有哪些比较好 2025-06-15 Kimi网页版 2024-03-17 deepseek网页在线使用网页版官方 2025-07-14 deepseek官网入口网页版官方正版 2025-08-15 deepseek网页版登录入口网页版官方网页版 2025-08-15 管道机器人十大排名 2025-06-06 豆包在线官网入口网页版 2025-04-09 ai一键消衣物破解版下载免费版 2025-03-27 ikanbot爱看机器人官网网页版官方 2025-04-30 deepseek免费网页版登录入口网页版官方 2025-03-11 云启数据选品工具 2025-05-22 爱看机器人ikanbot官网 2025-08-27 deepseek的官方网站中文版官方免费版中文版 2025-03-10 deepseek官网入口网页版免费网页 2025-08-29 ai智能换脸与李沁大战2夕颜视频 2025-03-24 kimi官网入口网页版链接官方 2025-03-27 DeepSeek官网 2025-07-16 造成java.lang.NoClassDefFoundError错误的原因及解决办法 2025-08-15 DeepSeek在线使用-免费试用DeepSeek网页版-AMZ123跨境导航 2025-07-25 kimi网页版 2025-09-01 Virtual Media Script Writer 2024-09-05 免费试用DeepSeek网页版,DeepSeek在线使用 2025-03-25 豆包ai在线使用入口网页版 2025-03-28 deepseek在线使用无需登录网页版 2025-08-16 即梦ai电脑版免费下载中文版官方免费版 2025-03-09 夸智AI 2025-02-27 deepseek chat官网入口网页版官方正版 2025-08-06 deepseek网页版免费网页版 2025-03-10 即梦ai无限积分破解版最新下载 2025-03-16

热评文章 机器人核心三大部件有哪些 2025-09-05 豆包ai是什么意思 2025-09-05 ai写文章怎么用手机写的 2025-09-05 讯飞统一认证平台下载 2025-09-05 讯飞新零售工作怎么样呢 2025-05-12 ai写作创作家推荐软件 2025-05-12 千问通义官网入口官方 2025-08-22 科大讯飞ai鼠标使用说明手册 2025-05-12 ai视频免费制作软件手机版 2025-08-29 heygen官方旗舰店 2025-05-11 腾讯音乐人pc端开放平台上传 2025-05-11 aippt生成软件免费 2025-06-09 vogue runway官方app 2025-05-11 电脑版ai写作软件哪个好用点呢 2025-05-11 ai绘画软件怎么下载字体包安装到电脑 2025-05-11 剪辑学会 2025-08-12 gpt学术优化网站推荐 2025-05-12 startai插件破解版中文版免费版破解版 2025-09-05 ai如何填充颜色快捷键是哪个 2025-05-10 百川ai智能大模型怎么样好用吗 2025-05-21 可以陪老人聊天的机器人 2025-08-11 aigc如何降重 2025-08-16 视频ai制作软件下载免费版 2025-05-10 讯飞通信 2025-07-18 智能ai换脸技术有哪些 2025-07-14 讯飞星火助手有什么用 2025-05-09 ai界面没有工具栏怎么办 2025-05-09 剪映电脑版草稿怎么从电脑调取 2025-05-09 百度智能云控制台登录入口官方网页版 2025-05-09 华为平板matepadair12寸处理器 2025-05-09

最新文章 pptai一键生成免费怎么弄 2025-12-04 抖音的ai人声怎么做的详细步骤 2025-12-04 小龙赚钱app下载安装官方 2025-12-04 怎样安装deepseek小程序 2025-12-04 deepseek概念股有哪些代码 2025-12-04 电脑下载剪映不能安装怎么办 2025-12-04

金华奇玑电子商务有限公司 夸智网——AI时代、人工智能、大模型、机器人、人工智能体

本站部分信息来自互联网收集,仅供学习和交流,如有侵权、后门、不妥之处,请联系我们进行删除处理。

浙ICP备15009899号-3

返回顶部

暗黑模式