【Unity学习笔记】AssetBundle

这篇具有很好参考价值的文章主要介绍了【Unity学习笔记】AssetBundle。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


什么是AB包?

AssetBundle是Unity提供的一种用于存储资源的压缩集合,它可以存储任何一种Unity可以识别的资源,如模型,纹理图,音频,场景等资源。也可以加载开发者自定义的二进制文件。

为什么使用AB包?

Resources打包时会将所有的资源统统打包到Resources中,这意味着即使你只想要其中的部分资源,也需要对所有资源全部打包带走;并且由于它是只读的,所以我们不能随意地修改包的内容。

相对的使用AB包能够分别将不同的资源打包到独立的包体内,AB包存储路径可自定义,压缩方式可自定义,后期也可以对已经打包的内容进行动态更新。

AB包可以节约包体资源大小。一方面在压缩时AB包允许更好的压缩方式,以及选取的压缩资源也可以随意选择。另一方面,例如在游戏客户端的时候,由于AB包是可修改的,因此可以减少初始的安装大小,在安装游戏的时候我们可以设置一个可供游戏运行的较小的AB包,当玩家更新时则可以把其余的AB包内容下载完。

AB包还可以方便我们进行热更新,例如玩王者的时候,我们并没有下载更新,而游戏界面却更新了。这可以通过游戏内部对已经下载的AB包资源进行热更新而实现。而在游戏需要更新下载的时候,通常是先让客户端与服务器通信后,获取资源服务器的地址,然后和资源服务器的AB包进行对比来判断需要更新的资源。


如何导出AB包

在安装了AB包服务后如何导出AB包?

【Unity学习笔记】AssetBundle,Unity学习笔记,unity,学习,笔记
1.选中物体,在Inspector界面下方输入(选择)绑定的包体名称
【Unity学习笔记】AssetBundle,Unity学习笔记,unity,学习,笔记
2.在AssetBundles面板查看已经打的包
【Unity学习笔记】AssetBundle,Unity学习笔记,unity,学习,笔记
3.选择导出选项

此处介绍一下导出选项

属性 选项
Build Target 选项对应导出的平台
Output 导出路径,AB包根路径AssetBundles与Asset同级
Clear Folders 清空导出文件夹
Copy to StreamingAssets 导出完毕后,导出的AB包复制到Assets文件夹中的StreamingAssets中

一些比较重要的参数

属性 选项
Compression 压缩模式:No Compression无压缩,不用解包,优点是读取快,但是文件大
LZMA标准压缩,压缩率高,但解包麻烦
LZ4区块压缩,当使用包内的资源时,只会解压对应的chunk,内存占用率低, 强烈推荐
Exclude Type Information 不包含资源类型信息
Force Rebuild 强制重构包内所有内容
Ignore Type Tree Changes 在执行增量构建检查时忽略类型树更改
Append Hash assetBundle 名称附加哈希(哈希寻址,文件校验)
Strict Mode 如果在此期间报告任何错误,则构建无法成功
Dry Run Build 进行干运行构建。此选项允许您针对 AssetBundle 进行干运行构建,但不实际构建它们。启用此选项后,BuildPipeline.BuildAssetBundles 仍将返回 AssetBundleManifest 对象,其中包含有效的 AssetBundle 依赖关系和哈希。

此外在unity中,C#是不能打包成AB包的,因此我们需要学习Lua(哈哈,太搞笑了)。打包成AB包时物体上的C#脚本其实只包含了对应FileID的映射。

【Unity学习笔记】AssetBundle,Unity学习笔记,unity,学习,笔记
4.在Inspect中打开对应资源可以检查导出完毕的AB包中的信息

此外,被打包的物体所使用的那些资源,例如shader,sprite等,即使没有主动将它们打包,它们也会被自动地打包(并且默认与使用它的物体在同一个包体中)。此时我们可以在AssetLabel里选择它属于哪个包。但是要注意,如果物体所依赖的资源被打到其他的包中,那么单独加载物体往往会造成其他依赖资源的丢失,因此在加载这个物体的时候我们还需要同时加载它的依赖包。

AB包导出文件

【Unity学习笔记】AssetBundle,Unity学习笔记,unity,学习,笔记

打包完成后,每个包会对应生成一个包和一个对应的manifest清单,此外还有一个与文件夹同名的包,称为主包,它储存了包与包之间的依赖关系的信息。所有的包没有后缀名,是二进制文件。Manifest包含了资源中的信息。

我们往往会勾选StreamingAssets,这是为了方便在代码中进行调用,通常使用:

Application.streamingAssetsPath + "/" +"包名"

来读取AB包的路径


如何使用AB包

AB包的加载

AB包的加载分为两步,第一步先加载AB包,第二步加载包内对应的资源

同步加载

最简单的方法就是同步的方式加载AB包资源,所有代码全部依次执行

首先加载AB包

AssetBundle AB = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "包名");

然后加载资源,资源加载有两种方式,一种通过泛型加载,另一种直接加载并指定类型。

// T对应加载的资源的类型
T obj = AB.LoadAsset<T>("包内资源名");
// T对应加载的资源的类型
T obj = AB.LoadAsset("包内资源名", typeof(T)) as T;

从实用性上来说第一种加载方式好,但是从实践上来说第二种更好,因为Lua不支持泛型。


在这种情况下

异步加载

异步加载是我们推荐的方式,因为在Unity是单线程的,我们不希望同步加载时由于资源数量多导致的主线程阻塞,这会造成游戏卡死。说到异步加载,那第一个肯定想到的是协程,除了用协程加载,AB包也提供了一些异步加载方法。

    IEnumerator LoadABres(string ABName, string resName)
    {
        AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/" + ABName);
        yield return abcr;
        AssetBundleRequest abq = abcr.assetBundle.LoadAssetAsync(resName, typeof(Sprite));
        yield return abq;
        // 以加载Image组件的Sprite为例
        Sprite.sprite = abq.asset as Sprite;
    }

AB包的卸载

AssetBundle.UnloadAllAssetBundles(true);
AssetBundle.UnloadAllAssetBundles(false);

UnloadAllAssetBundles方法可以一键卸载全部的AB包,其中包含两种模式,true模式下会直接卸载场景中的AB包,这会导致场景资源丢失。所以推荐使用false,false时会卸载全部AB包并且场景资源不丢失。

同样的我们可以用Unload方法卸载指定AB包,同样的true和false。

AB.Unload(true);
AB.Unload(false);

依赖加载

如果一个模型依赖一个资源,我们可以将两个包都加载。但是如果一个模型依赖好多资源,难道我们要手动加载这么多包?更糟糕的是如果你不知道依赖包是哪个该怎么办?

因此我们需要主包来获取依赖信息

// 加载主包
AssetBundle abMain = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "主包包名");
// 获取主包清单
AssetBundleManifest abManifest = abMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
// 从清单中获取依赖信息并保存在一个字符串数组中
string[] strs = abManifest.GetAllDependencies("需要加载的包名");
// for循环或者foreach都可以循环加载依赖包
foreach (string str in strs)
{
	AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + str);
}

有个问题,现在我们的确加载了使用包体的资源。但是如果在另一个包中,它的依赖包和这个包的依赖包是相同的,那么如果我们加载了另一个包,就会报错!因为同一个依赖包被加载了两次。

为了避免这种问题,我们需要一个管理器来统一管理资源包的加载卸载!


AB包资源管理器

首先我们思考,一个资源管理器应当有哪些特点:

  • 全局唯一,否则其他类的调用依旧会导致重复加载(单例模式)
  • 字典存储,列出一个包体使用清单,并且键值对能避免重复写入
  • 异步加载,保证主线程安全

那么一个单例模式的资源管理器将是最佳的选择。

主要过程分为四步:

  • 写一个函数实现读取主包获取依赖关系
  • 定义一个字典以键值对形式存储包名和AB包资源之间的映射,字典可以避免重复读取同一个包
  • 重写Unity的读取AB包方法,使之先读取主包获取所读AB包的依赖关系,随后读取该AB包和所有依赖包
  • 定义卸载方法,清空字典
  • (以及其他的自定义可拓展的方法)

这里仅给出一小段代码:

定义一个DontDestroyOnLoad的接受泛型的单例基类

/// <summary>
/// 该单例继承于Mono,并且不会随着场景的切换而销毁
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class DDOLSingletonMono<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T _instance;
    public static T Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = FindObjectOfType<T>();
                if (_instance == null)
                {
                    GameObject obj = new GameObject();
                    obj.name = typeof(T).Name;
                    DontDestroyOnLoad(obj);
                    _instance = obj.AddComponent<T>();
                }
            }
            return _instance;
        }
    }
}

定义一个ABManager,它继承了上述基类,并在其内定义管理方法

    /// <summary>
    /// 加载AB包
    /// </summary>
    /// <param name="abName"></param>
    public void LoadAB(string abName)
    {
        // 获取主包
        if (mainAB == null)
        {
            mainAB = AssetBundle.LoadFromFile(PathUrl + MainABName);
            manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }
        AssetBundle ab = null;
        // 获取所用资源包依赖信息
        string[] relys = manifest.GetAllDependencies(abName);
        foreach (string rely in relys)
        {
            // 判断依赖包是否已加载
            if (!abDic.ContainsKey(rely))
            {
                ab = AssetBundle.LoadFromFile(PathUrl + rely);
                abDic.Add(rely, ab);
            }
        }
        // 加载资源包
        if (!abDic.ContainsKey(abName))
        {
            ab = AssetBundle.LoadFromFile(PathUrl + abName);
            abDic.Add(abName, ab);
        }
    }
    /// <summary>
    /// 异步加载资源,GameObject类型可直接帮助实例化
    /// </summary>
    /// <param name="abName">加载的资源包</param>
    /// <param name="resName">加载的资源名称</param>
    /// <param name="callBack"></param>
    public void LoadResAsync(string abName, string resName, UnityAction<Object> callBack)
    {
        StartCoroutine(LoadResAsyncCoroutine(abName, resName, callBack));
    }
    private IEnumerator LoadResAsyncCoroutine(string abName, string resName, UnityAction<Object> callBack)
    {
        LoadAB(abName);
        // 如果是GameObject,帮助实例化
        AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName);
        yield return abr;
        if (abr.asset == null)
        {
            Debug.LogError("异步加载失败!读取资源为空!");
        }
        if (abr.asset is GameObject)
            callBack(Instantiate(abr.asset));
        else
            callBack(abr.asset);
    }

其他代码也大同小异,无非就是重写官方的三种同步加载和异步加载的方法,使之先读取依赖包,顺便能帮助GameObject进行实例化。
具体代码可以查看【唐老狮】Unity热更新之AssetBundle

使用AB包管理器,就可以避免项目中混乱的包体关系,推荐指数五颗星。文章来源地址https://www.toymoban.com/news/detail-603955.html

到了这里,关于【Unity学习笔记】AssetBundle的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity AssetBundle资源热更插件

    取消 IsEditorMode 勾选: 采用AssetBundle的方式加载游戏内的资源 激活 IsEditorMode 勾选: 使用AssetDatabase.LoadAssetAtPath的方式加载 仅Editor 温馨提示: IsEditorMode 受到宏限制 如果你非 UNITY_EDITOR模式下 ( 当年在真机的时候 ) IsEditorMode强制为False 避免用户打包后忘记关了 新建一个AssetBundl

    2024年02月11日
    浏览(42)
  • Unity知识点 -- AssetBundle(AB包)

    特定于平台的资产压缩包,类似于压缩文件 资产包括:模型、贴图、预制体、音效、材质球等 2.1 相对于 Resources 下的资源,AB 包更好管理资源 Resource:打包时定死,只读,无法修改 AB包:存储位置可以自定义,压缩方式可以自定义,后期可以动态更新,通过 AB 包可以做热更

    2024年02月13日
    浏览(43)
  • Unity-AssetBundle Browser 打包和加载

    进入unity手册中,搜素 Unity Asset Bundle Browser 工具,选择你使用的版本号,根据显示出的操作进行资源导入即可。 注:有的版本可能没有资源链接,可以百度一下有很多。 1、制作预制体(省略)  2、选择一个预制体,在Inspector窗口下方,设置预制体的ab包名(包名只能为小写字

    2024年04月13日
    浏览(31)
  • [游戏开发][Unity]Assetbundle打包与资源加载框架

    我会分三个篇章写整个框架分别是: AB打包篇 AB下载篇 AB加载篇 整个框架内容比较多,属于企业级方案,涉及到增量打包、打包策略、AB包下载、边玩边下、资源管理系统,资源加载系统等功能。 Unity小白看本系列文章可能比较吃力。如果我哪里写的不好,影响理解了,欢迎

    2024年02月13日
    浏览(51)
  • Unity热更新——AssetBundle(AB包)+管理器

    游戏或者软件更新时,无需重新下周客户端进行安装,而是在应用程序启动的情况下,在内部进行的资源或者代码更新 特定于平台的资产压缩包,有点类似压缩文件,资产包括:模型、贴图、预设体、音效、材质球等等 相对Resources下的资源,AB包更好管理资源,区别是: A

    2024年02月04日
    浏览(34)
  • Unity中AssetBundle的变体(Varient)使用教程

    在使用Unity的AssetBundle过程中,选中资源物体之后,发现右下角的AssetBundle面板,除了有一个命名标签外,还有一个Varient标签,这边文章主要介绍下这个标签的用法,如下图: 多语言 :在做游戏开发的过程中,会遇到多语言问题,特别是现在推行的游戏全球化,所以支持多语

    2024年02月16日
    浏览(39)
  • Unity引擎打包AssetBundle后模型网格数据丢失问题

    大家好,我是阿赵。 在项目里面,有时候会遇到这样一个问题。在Unity编辑器里面编写了一个shader,在编辑器看,效果都是没有问题的。但如果把资源打包成AssetBundle后,会发现shader的表现不对了。遇到了这种问题的时候,一般人会各自的怀疑,怀疑是不是shader写得不对,导

    2024年02月07日
    浏览(48)
  • Unity的AssetBundle系统来动态加载FBX模型

    在Unity中,可以使用C#脚本和Unity的AssetBundle系统来动态加载FBX模型。以下是一个简单的示例,演示如何动态加载FBX模型: 准备FBX模型 首先,准备一个或多个FBX模型,并将它们导入到Unity项目中。确保每个FBX模型都有一个独立的游戏对象,并且已经被正确地设置为“Static”或“

    2024年02月06日
    浏览(41)
  • Unity 解决SpriteAtlas图集打包AssetBundle白图问题

    之前文档上说勾选了Include in build之后,就不需要自己增加一个Binding脚本,但是仍然会弹出警告,并且会出现白图现象 Tight Packing 勾选之后当Sprite有透明通道可能会出现错位 不推荐勾选 选项取消勾选之后打包AssetBundle会报警告 并且出现白图现象 那是因为没有进行bing  Sprite

    2024年02月11日
    浏览(41)
  • 【Unity】AssetBundle资源异步加载以及AB包卸载

    以下代码是基于上一篇文章《AssetBundle资源同步加载》的代码新增了异步加载和AB包卸载功能,有兴趣的同学可以去看看我的上一篇文章。 由于异步加载需要配合协程进行功能开发,所以我对之前封装的AB包资源加载管理器进行修改,改为继承MonoBehaviour的单例模式。 主要修改

    2023年04月08日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包