游戏热更新——AssetBundle

news2024/12/29 10:35:48

AssetBundle

AssetBundle的定义与使用

  AssetBundle是一个压缩包包含模型、贴图、预制体、声音、甚至是整个场景,可以在游戏运行的时候被加载

  AssetBundle自身保存着相互的依赖关系

  压缩包可以使用LZMA和LZ4压缩算法,减少包大小,更快的进行网络传输

  把一些可以下载内容AssetBundle里面,可以减少安装包的大小

什么是AssetBundle

  是一个存在硬盘上的文件,可以称之为压缩包,这个压缩包可以认为是一个文件夹,里面包含了多个文件。这些文件分为两类:serialized file 和 resource files(序列化文件和源文件)

    serialized file:资源被打碎放在一个对象中,最后统一被写进一个单独的文件(只有一个)

    resource file:某些二进制资源(图片、声音)被单独保存,方便快速加载

  是一个AssetBundle对象,可以通过代码从一个特定的压缩包加载出来的对象。这个对象包含了所有当初添加到这个压缩包里面的内容,可以通过这个对象加载出来使用

AssetBundle使用流程图

在这里插入图片描述

在这里插入图片描述

AssetBundle使用流程(AB)

  指定资源的AssetBundle属性(xxxa/xxx)这里xxxa会生成目录,名字为xxx

  构建AssetBundle包

  上传AB包

  加载AB包和包里面的资源

利用代码打包示例

using System.IO;
using UnityEditor;

public class CreateAssetBundles
{
    [MenuItem("Assets/Build AssetBundles")]
    static void BuildAllAssetBundles()
    {
        string dir = "AssetBundles";
        if (!Directory.Exists(dir))
        {
            Directory.CreateDirectory(dir);
        }
        BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
    }
}

利用代码加载本地AB包示例

using UnityEngine;

public class LoadFromFileExp : MonoBehaviour 
{
    private void Start()
    {
        AssetBundle ab = AssetBundle.LoadFromFile("AssetBundles/wall.unity3d");

        GameObject obj = ab.LoadAsset<GameObject>("wall");
    
        Instantiate(obj);
    }
}

AssetBundle 分组策略(仅供参考)

  逻辑实体分组

    一个UI界面或者所有UI界面一个包(这个界面里面的贴图和布局信息一个包)

    一个角色或者所有角色一个包(这个角色里面的模型和动画一个包)

    所有的场景所共享的部分一个包(包括贴图和模型)

  按照类型分组

    所有声音资源打成一个包,所有Shader打成一个包,所有模型打成一个包,所有材质打成一个包

  按照使用分组

    把在某一时间内使用的所有资源打成一个包。可以按照关卡分,一个关卡所需要的所有资源包括角色、贴图、声音等打成一个包。也可以按照场景分,一个场景所需要的资源一个包

AssetBundle 分组策略——总结

  把经常更新的资源放在一个单独的包里面,跟不经常更新的包分离

  把需要同时加载的资源放在一个包里面

  可以把其他包共享的资源放在一个单独的包里面

  把一些需要同时加载的小资源打包成一个包

  如果对于同一个资源有两个版本,可以考虑通过后缀来区分:比如 unity3dv1unity3dv2

依赖打包

在这里插入图片描述

打包选项(AssetBundle压缩方式)

  Build的路径(随意只要是在硬盘上都可以的)

  BuildAssetBundleOptions

    BuildAssetBundleOptions.None:使用LZMA算法压缩,压缩的包更小,但是加载的时间更长。使用之前需要整体解压。一旦被解压,这个包会使用LZ4重新压缩。使用资源的时候不需要整体解压。在下载的时候可以使用LZMA算法,一旦他被下载了之后,它会使用LZ4算法保存到本地上

    BuildAssetBundleOptions.UncompressedAssetBundle:不压缩,包大,加载快

    BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4压缩,压缩率没有LZMA高,但是可以加载指定资源而不用解压全部

    使用LZ4压缩,可以获得可以跟不压缩相媲美的加载速度,而且比不压缩文件更小

  BuildTarget

    选择build出来的AB包要使用的平台

在这里插入图片描述

从内存中加载 AssetBundle

IEnumerator Start()
    {
        AssetBundleCreateRequest ab = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes("AssetBundles/wall1.unity3d"));

        yield return ab;

        AssetBundle asb = ab.assetBundle;

        GameObject obj = asb.LoadAsset<GameObject>("wall1");

        Instantiate(obj);
    }

从本地加载 AssetBundle

IEnumerator Start()
    {
        AssetBundleCreateRequest ab = AssetBundle.LoadFromFileAsync("AssetBundles/wall1.unity3d");

        yield return ab;

        AssetBundle asb = ab.assetBundle;

        GameObject obj = asb.LoadAsset<GameObject>("wall1");

        Instantiate(obj);
    }

使用 WWW.LoadFromCacheOrDownload 下载并加载 AssetBundle

IEnumerator Start()
    {
        while (!Caching.ready)
        {
            yield return null;
        }
        WWW www = WWW.LoadFromCacheOrDownload(@"E:\Work\Work2\AssetBundleTest\\AssetBundles\wall1.unity3d", 1);
        yield return www;

        if(!string.IsNullOrEmpty(www.error))
        {
            Debug.LogError(www.error);
            yield break;
        }

        AssetBundle asb = www.assetBundle;

        GameObject obj = asb.LoadAsset<GameObject>("wall1");

        Instantiate(obj);
    }

从服务器端下载 AssetBundle

IEnumerator Start()
    {
        while (!Caching.ready)
        {
            yield return null;
        }
        WWW www = WWW.LoadFromCacheOrDownload(@"http://localhost/AssetBundles/wall1.unity3d", 1);
        yield return www;

        if(!string.IsNullOrEmpty(www.error))
        {
            Debug.LogError(www.error);
            yield break;
        }

        AssetBundle asb = www.assetBundle;

        GameObject obj = asb.LoadAsset<GameObject>("wall1");

        Instantiate(obj);
    }

使用 UnityWebRequest 来加载 AssetBundle

IEnumerator Start()
    {
        string uri = @"file:///E:\Work\Work2\AssetBundleTest\\AssetBundles\wall1.unity3d";
        UnityWebRequest uwr = UnityWebRequestAssetBundle.GetAssetBundle(uri);

        yield return uwr.SendWebRequest();

        AssetBundle ab = DownloadHandlerAssetBundle.GetContent(uwr);


        GameObject obj = ab.LoadAsset<GameObject>("wall1");

        Instantiate(obj);
    }

加载 Manifest

IEnumerator Start()
    {
        string uri = @"file:///E:\Work\Work2\AssetBundleTest\\AssetBundles\wall1.unity3d";
        UnityWebRequest uwr = UnityWebRequestAssetBundle.GetAssetBundle(uri);

        yield return uwr.SendWebRequest();

        AssetBundle ab = DownloadHandlerAssetBundle.GetContent(uwr);

        GameObject obj = ab.LoadAsset<GameObject>("wall1");

        Instantiate(obj);

        AssetBundle manifestAb = AssetBundle.LoadFromFile("AssetBundles/AssetBundles");
        AssetBundleManifest manifest = manifestAb.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

        foreach(var a in manifest.GetAllAssetBundles())
        {
            print(a);
        }

        string[] strs = manifest.GetAllDependencies("wall1.unity3d");
        foreach(var a in strs)
        {
            print(a);
            AssetBundle.LoadFromFile(@"AssetBundles/" + a);
        }
    }

AssetBundle 的卸载

  卸载有两个方面:

    减少内存使用

    有可能导致丢失

  AssetBundle.Unload(true):卸载所有资源,即使有资源被使用着

    1.在关卡切换、场景切换

    2.资源没被用的时候调用

  AssetBundle.Unload(false):卸载所有没有被使用的资源

    个别资源的卸载:

      1.通过Resource.UnloadUnusedAssets

      2.场景切换的时候自动卸载

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

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

相关文章

栈(Stack)and leetcode刷题

栈&#xff08;Stack&#xff09;and leetcode刷题 1. 栈&#xff08;Stack&#xff09;的概念2. 栈&#xff08;Stack&#xff09;的实现2.1 用数组实现2.2 用链表实现2.2.1 用单链表实现 3. leetcode刷题3.1 括号匹配问题3.2 栈的弹出压入序列3.3 逆波兰表达式求值中缀表达式…

Cartographer重入门到精通(二):运行作者demo及自己的数据集

在demo数据包上运行cartographer 现在Cartographer和Cartographer的Ros包已经都安装好了&#xff0c;你可以下载官方的数据集到指定的目录&#xff08;比如在Deutsches Museum用背包采集的2D和3D 数据&#xff09;&#xff0c;然后使用roslauch来启动demo。 注&#xff1a;la…

一文了解5G新通话技术演进与业务模型

5G新通话简介 5G新通话&#xff0c;也被称为VoNR&#xff0c;是基于R16及后续协议产生的一种增强型语音通话业务。 它在IMS网络里新增数据通道&#xff08;Data Channel&#xff09;&#xff0c;承载通话时的文本、图片、涂鸦、菜单等信息。它能在传统话音业务基础上提供更多服…

拓扑排序——AcWing 164. 可达性统计

目录 拓扑排序 定义 运用情况 注意事项 解题思路 AcWing 164. 可达性统计 题目描述 运行代码 代码思路 改进思路 拓扑排序 定义 拓扑排序&#xff08;Topological Sort&#xff09;是对有向无环图&#xff08;Directed Acyclic Graph&#xff0c;简称DAG&#xff…

【论文阅读笔记】ASPS: Augmented Segment Anything Model for Polyp Segmentation

1.论文介绍 ASPS: Augmented Segment Anything Model for Polyp Segmentation ASPS&#xff1a;用于息肉分割的扩展SAM模型 2024年 arxiv Paper Code 2.摘要 息肉分割在结直肠癌诊断中起着至关重要的作用。最近&#xff0c;Segment Anything Model(SAM)的出现利用其在大规模…

去水印小程序源码修复版-前端后端内置接口+第三方接口

去水印小程序源码&#xff0c;前端后端&#xff0c;内置接口第三方接口&#xff0c; 修复数据库账号密码错误问题&#xff0c;内置接口支持替换第三方接口&#xff0c; 文件挺全的&#xff0c;可以添加流量主代码&#xff0c;搭建需要准备一台服务器&#xff0c;备案域名和http…

【JVM实战篇】内存调优:内存问题诊断+案例实战

文章目录 诊断内存快照在内存溢出时生成内存快照MAT分析内存快照MAT内存泄漏检测的原理支配树介绍如何在不内存溢出情况下生成堆内存快照&#xff1f;MAT查看支配树MAT如何根据支配树发现内存泄漏 运行程序的内存快照导出和分析快照**大文件的处理** 案例实战案例1&#xff1a;…

交换机和路由器的工作流程

1、交换机工作流程&#xff1a; 将接口中的电流识别为二进制&#xff0c;并转换成数据帧&#xff0c;交换机会记录学习该数据帧的源MAC地址&#xff0c;并将其端口关联起来记录在MAC地址表中。然后查看MAC地址表来查找目标MAC地址&#xff0c;会有一下一些情况&#xff1a; MA…

java.sql.SQLException: Before start of result set

情况描述&#xff0c;在通过JDBC连接数据库时&#xff0c;想直接判断获取的值是否存在&#xff0c;运行时报错。 翻译&#xff1a; 在开始结果集之前 报错截图 解决问题的方法&#xff1a;对结果集ResultSet进行操作之前&#xff0c;一定要先用ResultSet.next()将指针移动至…

4K60无缝一体矩阵 HDMI2.0功能介绍

关于GF-HDMI0808S 4K60无缝一体矩阵的功能介绍&#xff0c;由于直接针对GF-HDMI0808S型号的具体信息较少&#xff0c;我将结合类似4K60无缝HDMI矩阵的一般功能特性和可能的GF-HDMI0808系列产品的特点来进行说明。请注意&#xff0c;以下信息可能不完全针对GF-HDMI0808S型号&…

vienna整流器的矢量分析

Vienna整流器使用六个二极管和六个IGBT&#xff08;或MOSFET&#xff09;组成&#xff0c;提供三个电平&#xff1a;正极电平&#xff08;P&#xff09;、中性点电平&#xff08;O&#xff09;和负极电平&#xff08;N&#xff09;。通过对功率管的控制&#xff0c;Vienna整流器…

xmind梳理测试点,根据这些测试点去写测试用例

基本流&#xff08;冒烟用例必写&#xff09; 备选流 公共测试点&#xff1a;

算法笔记——LCR

一.LCR 152. 验证二叉搜索树的后序遍历序列 题目描述&#xff1a; 给你一个二叉搜索树的后续遍历序列&#xff0c;让你判断该序列是否合法。 解题思路&#xff1a; 根据二叉搜索树的特性&#xff0c;二叉树搜索的每一个结点&#xff0c;大于左子树&#xff0c;小于右子树。…

【企业级监控】Zabbix实现邮箱报警

Zabbix监控自动化 文章目录 Zabbix监控自动化资源列表基础环境前言四、Zabbix邮件告警4.1、实现报警所需的条件4.1.1、告警媒介4.1.2、触发器&#xff08;trigger&#xff09;4.1.3、动作&#xff08;action&#xff09; 4.2、配置告警媒介4.2.1、设置告警媒介参数4.2.2、启用此…

SpringCloud教程 | 第八篇: 使用seata处理分布式事务

1、参考程序员江小北 2、打算降低nacos版本&#xff0c;先学通再看看升级到高版本nacos能不能正常使用。 3、nacos用1.4.1&#xff0c;正常启动单机版的了 4、seata用2.0.0 我看江小北说用的1.4.0的seata&#xff0c;但是图片中的目录文件都找不到&#xff0c;倒是在2.0.0的…

弥合人类与人工智能的知识差距:AlphaZero 中的概念发现和迁移(1)

文章目录 一、摘要二、简介三、相关工作3.1 基于概念的解释3.2 强化学习中生成解释3.3 国际象棋与人工智能 四、什么是概念&#xff1f;五、发掘概念5.1 挖掘概念向量5.1.1 静态概念的概念约束5.1.2 动态概念的概念约束 5.2 过滤概念 一、摘要 人工智能&#xff08;AI&#xff…

计算机网络--tcpdump和iptable设置、内核参数优化策略

tcpdump工具 tcpdump命令&#xff1a; 选项字段&#xff1a; 过滤表达式&#xff1a; 实用命令&#xff1a; TCP三次握手抓包命令&#xff1a; #客户端执行tcpdump 抓取数据包 tcpdump -i etho tcp and host 192.168.12.36 and port 80 -W timeout.pcapnetstat命令 netst…

昇思25天学习打卡营第12天 | ResNet50图像分类

昇思25天学习打卡营第12天 | ResNet50图像分类 文章目录 昇思25天学习打卡营第12天 | ResNet50图像分类ResNet网络模型残差网络结构Building BlockBottleneck 训练数据准备训练数据可视化 网络构建Build Block结构Bottleneck结构ResNet50网络 模型训练与评估训练验证迭代数据集…

Swiftui中几种常用的数据存储方式@AppStorage/UserDefaults/CoreData/File Storage/Keychain等

在 SwiftUI 中&#xff0c;有多种常用的数据存储方式&#xff0c;根据需求的不同&#xff0c;可以选择适合的存储方案。以下是几种常用的数据存储方式&#xff1a; AppStorage/UserDefaults/CoreData/File Storage/Keychain&#xff0c;分别来看一下他们的使用场景和区别。 1.…

【Linux 文件读写描述符重定向 Linux 一切皆文件缓冲区】

文章目录 一、文件的读写操作二、文件描述符三、文件重定向四、理解 Linux 一切皆文件五、文件缓冲区 一、文件的读写操作 文件内容属性 当文件没有被操作的时候&#xff0c;一般文件还是在磁盘当中 文件操作文件内容的操作文件属性的操作&#xff0c;文件操作有可能即改变内容…