Unity中的AssetBundle

news2024/11/28 8:48:14

AssetBundle的概念

AssetBundle又称AB包,是Unity提供的一种用于存储资源的资源压缩包,是对Unity 初始Resources的一种扩展;一般使用的策略是把必须的资源和不需要更新的资源放在Resources文件夹下,其他的资源放在AssetBundle下面。

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

AssetBundle的优势

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

AssetBundle和Resources的比较

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

AssetBundle的特性

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

AssetBundle全打包流程

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

  1. AssetBundleBrowser插件的获取 Unity 2019版本可以直接在Windows —>PackageManager里面找到此插件并直接安装
    在这里插入图片描述
  2. 2020版本之后或其它版本可能在1方法中找不到此插件,可以通过去github搜索下载压缩包,将下载后的安装包解压到Unity工程的Packages文件夹下 (一定要解压)

AssetBundleBrowser面板的使用

正确获取到并安装完插件后,通过 Windows ----> AssetBundle Browser下打开AB包管理面板 一共有三个面板

Configure面板 :能查看当前AB包及其内部资源的基本情况(大小,资源,依赖情况等)

在这里插入图片描述

Build面板:负责AssetBundle打包的相关设置 按Build即可进行打包
在这里插入图片描述

三种压缩方式

NoCompression:不压缩,解压快,包较大,不建议使用。
LZMA: 压缩最小,解压慢,用一个资源要解压包下所有资源。
LZ4: 压缩稍大,解压快,用什么解压什么,内存占用低,一般建议使用这种。
一般需要进行更改的设置即为图中勾选的相关选项设置。

Inspect面板:主要用来查看已经打包后的AB包文件的一些详细情况(大小,资源路径等)
在这里插入图片描述
3、设置资源所属的AssetBundle包

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

AssetBundle加载和卸载的代码示例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ABLoadTest : MonoBehaviour
{
    private Dictionary<string, AssetBundle> abCache;
    private AssetBundle mainAB = null; //主包
    private AssetBundleManifest mainManifest = null; //主包中配置文件---用以获取依赖包
                                                     

    private string basePath
    {
        get
        {
#if UNITY_EDITOR || UNITY_STANDALONE
            return Application.dataPath + "/StreamingAssets/";
#elif UNITY_IPHONE
                return Application.dataPath + "/Raw/";
#elif UNITY_ANDROID
                return Application.dataPath + "!/assets/";
#endif
        }
    }

    void Start()
    {
        abCache = new Dictionary<string, AssetBundle>();

        var ab = LoadABTest();
        GameObject model = ab.LoadAsset<GameObject>("Cube");
        var b = Instantiate<GameObject>(model);
        // dosomething


    }

    AssetBundle LoadABTest()
    {
        AssetBundle ab;
        string abName = "3dmodel.first";
        if (mainAB == null)
        {
            mainAB = AssetBundle.LoadFromFile(basePath + "StandaloneWindows");
            mainManifest = mainAB.LoadAsset<AssetBundleManifest>("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))
        {
            Debug.Log($"have load {abName}");
            return abCache[abName];
        }
        else
        {
            ab = AssetBundle.LoadFromFile(basePath + abName);
            abCache.Add(abName, ab);
            Debug.Log($"new load {abName}");
            return ab;
        }
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.A)) // 同步加载
        {
            var ab = LoadABTest();
            GameObject model = ab.LoadAsset<GameObject>("Cube");
            var b = Instantiate<GameObject>(model);
        }
        else if (Input.GetKeyDown(KeyCode.S))// 异步加载
        {
            var ab = LoadABTest();
            StartCoroutine(LoadResAsyncTest(ab));
            
        }
        else if (Input.GetKeyDown(KeyCode.D))// 单个卸载
        {
            UnLoad("3dmodel.first");
            Debug.Log("have UnLoadAll 3dmodel.first");

        }
        else if (Input.GetKeyDown(KeyCode.F))// 全部卸载
        {
            UnLoadAll();
            Debug.Log("have UnLoadAll");
        }

    }

    private IEnumerator LoadResAsyncTest(AssetBundle ab)
    {
        if (ab == null) yield return null;
        var model1 = ab.LoadAssetAsync<GameObject>("Cube");
        yield return model1;
        var async_model = Instantiate((GameObject)model1.asset);
        // dosomething
    }

    //====================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;
    }

}

参考资料:Unity中AB包详解(超详细,特性,打包,加载,管理器)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/3730.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【微信小程序】flex布局

&#x1f3c6;今日学习目标&#xff1a;flex布局 &#x1f603;创作者&#xff1a;颜颜yan_ ✨个人主页&#xff1a;颜颜yan_的个人主页 ⏰预计时间&#xff1a;20分钟 &#x1f389;专栏系列&#xff1a;微信小程序开发 文章目录前言Flex布局什么是flex&#xff1f;flex-direc…

Hive中内部表、外部表、分区表、分桶表之间的关系

文章目录Hive中内部表、外部表、分区表、分桶表之间的关系1.0&#x1f680;内部表2.0&#x1f440;外部表3.0&#x1fae5;内部表和外部表的差异3.0&#x1f418;分区表4.0&#x1f603;分桶表Hive中内部表、外部表、分区表、分桶表之间的关系 1.0&#x1f680;内部表 内部表&…

HEAD: HEtero-Assists Distillation for Heterogeneous Object Detectors

ECCV 2022 异质辅助蒸馏 Abstract Conventional knowledge distillation (KD) methods for object detection mainly concentrate on homogeneous teacher-student detectors. However, the design of a lightweight detector for deployment is often significantly differ…

计算机毕业设计(附源码)python智能仓储进出货管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

web前端期末大作业:基于HTML+CSS+JavaScript制作我的音乐网站(带设计报告)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

【python】都2022年不会还有人不会在电脑桌面上养宠物吧~

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ! 上班枯燥&#xff0c;对着冷冰冰的电脑&#xff0c;相信很多小伙伴即使摸鱼&#xff0c;心情也不愉快。 这时如果有个萌宠能大家进行实时互动&#xff0c;这该有多好呀。再无聊的工作也能增添那么一丝趣味。 今天博主就来给大…

2、Ubuntu下安装Vivado下的下载器驱动 Digilent 版本

简介 在Ubuntu下安装Vivado时&#xff0c;安装工具会提醒你&#xff0c;digilent驱动无法自动安装&#xff0c;需要手动安装&#xff0c;并且让用户参考UG973手册安装。 由于安装驱动很简单&#xff0c;不用麻烦大家去找手册了&#xff0c;这里直接给出安装方法 安装方法 …

【Pytorch Lighting】第 6 章:深度生成模型

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

FPGA HLS 卷积单元 数据类型hls优化约束设置

数据类型 自定义精度整形&#xff1a; ap_int<4> in1, in2; ap_int<8> concat; concat (in1, in2); // in1和in2拼起来&#xff08;按照补码拼起来&#xff09; /* 例子&#xff1a; in1 1, in2 -1 补码&#xff1a; in1 0001 in2 1001 > 11101 > 1…

Spring mvc处理异常

文章目录一、Handler ExceptionResolver处理异常二、ExceptionHandler注解三、重点&#xff1a;添加ExceptionHandler注解方法的形参只能是异常类型四、重点2&#xff1a;捕获所有方法的异常—ControllerAdvice注解五、总结六、ResponseStatusExceptionResolve自定义异常显示页…

[go学习笔记.第十一章.项目案例] 1.家庭收支记账软件项目

一.基本介绍 1.项目开发流程说明 2.项目需求说明 目标: 模拟实现一个基于文本界面的<<家庭记账软件>> 掌握初步的编程技巧和调试技巧 主要涉及以下知识点 : (1).局部变量和基本数据类型 (2).循环语句 (3).分支语句 (4).简单的屏幕输出格式控制 (5).进阶&#xff1…

刷题日记【第九篇】-笔试必刷题【杨辉三角的变形+计算某字符出现的次数+字符串通配符+统计每个月兔子的总数】

下列sql语句中哪条语句可为用户zhangsan分配数据库userdb表userinfo的查询和插入数据权限&#xff08;A&#xff09;。 常用的管理权限的命令为&#xff1a; grant select/insert/update/delete on 数据库名.表名 to 用户名‘该用户允许访问的ip’ 在oracle中&#xff0c;下面哪…

世界上只有一种共识算法,那就是Paxos

分布式系统原理系列目录 分布式系统的麻烦副本与一致性为什么需要一个分布式共识算法世界上只有一种共识算法&#xff0c;那就是PaxosCAP定理&#xff0c;说起来一句话&#xff0c;实际坑不少BASE&#xff0c;可用性高于强一致性分布式事务方案那么多&#xff0c;到底该选哪一…

计算机毕业设计(附源码)python智慧灭火器管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

大数据学习3.1 Hadoop环境准备

Hadoop环境Hadoop集群拓扑1、集群拓扑2、角色分配一、虚拟机安装二、虚拟机克隆1、克隆类型&#xff08;1&#xff09;完整克隆&#xff08;2&#xff09;链接克隆2、克隆步骤&#xff08;1&#xff09;克隆出master虚拟机&#xff08;2&#xff09;克隆出slave1虚拟机&#xf…

深入理解Linux文件描述符

>> Linux基础IO系列文章 1. Linux文件操作系统接口的学习使用 一、前言 在上一篇博客中&#xff0c;我们初步学习了Linux文件操作的系统接口&#xff0c;不难发现的是&#xff0c;这些系统函数都与文件描述符密切相关&#xff1a;open函数返回值是一个文件描述符&#…

Python编程挑战赛

题1&#xff1a;给小朋友分糖&#xff0c;每人分到糖的数量不同&#xff0c;输入小朋友的数量&#xff0c;计算至少需要多少糖&#xff1f; 思路&#xff1a;第1个小朋友1颗糖&#xff0c;第2个小朋友2颗糖&#xff0c;第3个小朋友3颗糖&#xff0c;……第n个小朋友n颗糖&#…

[数据结构]实现双向链表

作者&#xff1a; 华丞臧. 专栏&#xff1a;【数据结构】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 文章目录一、带头双向循环链表二、带头双向循环链表接口实现2.1 双向链表的初始化、打…

动态规划算法的题到底应该怎么做?思路教给你自己写

本文是我通过做题和借鉴一些前人总结的套路而得出的思路和方法&#xff0c;刚好这次CSDN第八周的周赛上出了三道动态规划的题目&#xff0c;我会结合题目对我的思路进行一个输出&#xff0c;会从最简单的一维dp开始讲解到二维dp&#xff0c;希望对你有帮助&#xff0c;有错误希…

MySQL数据库基础知识

今天是更新数据库的第一篇&#xff0c;关于数据库环境搭建问题博主先不在这里介绍了&#xff0c;博主今天是直接讲知识了&#xff0c;等以后的博客&#xff0c;博主再更新数据库搭建问题。在这里我们使用命令行式客户端&#xff0c;先不使用windows下的图形化界面&#xff0c;使…