Unity AssetsBundle打包

news/2024/5/13 2:24:55

为什么要使用AssetsBundle包

减少安装包的大小

默认情况下,unity编译打包是对项目下的Assets文件夹全部内容进行压缩打包

那么按照这个原理,你的Assets文件夹的大小将会影响到你最终打包出的安装包的大小,假如你现在正在制作一个游戏项目,最终打出来的安装包过大可能会对玩家下载造成一定影响,对一般玩家来讲,下载10M的游戏安装包远远比下载100M的游戏安装包要更容易接受,而AssetBundle可以将一部分资源打包到一个压缩包里面,游戏运行到需要的时候再进行下载这部分资源

游戏一共有100个关卡,如果将这些全部打包则打出的安装包大小为100M,如果现在用AssetBundle技术将后面90关的资源分离出去进行打包,那么你现在打包的游戏内容只有10个关卡的资源,安装包大小仅为10M,等玩家体验了前十关觉得还不错,当他想玩10关以后的游戏内容时,提示他需要下载资源包体验更多精彩内容,然后在unity中加载剩余的90关的资源包。这样做的话,你的游戏安装包仅仅10M大小,因为下载比较快,也比较省流量,可能会吸引更多的玩家下载体验你的游戏

可以用热更新修复游戏的Bug

经历千辛万苦,你的游戏终于上线了,突然收到玩家反馈,游戏第20关通关后无法进入到下一关,据查证,是原来打包时某个同事粗心大意把第21关的资源弄错了,导致加载21关时报错,,我们现在需要第一时间修复这个问题,如果是按照原来的打包方式,需要重新出一个100M的包,然后把重新出的包交给游戏平台审核,审核通过后,玩家需要卸载掉原来的游戏软件,重新下载你们新打出的安装包

如果按照另一种打包方式,我们在后面90关的AssetBundle包里修复这个问题,这时候通过服务器传输AssetBundle最新的包,会把有问题的资源进行修复,提示玩家bug已经修复,玩家进入游戏,发现可以把20关打通了,并且成功进入到下一关了,在这个游戏过程中,玩家不需要重新下载那100M的安装包,只需要打开游戏下载部分需要更新的资源,这部分资源一般会比较小,一般情况下可能是几十k的大小,就可以重新体验游戏了。这就是AssetBundle的第二个作用


AssetsBundle包的打包方式

设置资源标签

需要进行AssetsBundle打包的时候,需要先对要打包的资源的资源标签进行设置

调用Unity官方函数打出AssetsBundle包

对资源打包的设置完成后,通过在代码中调用Unity官方函数的方式,将所有设置了资源标签的资源打出AssetsBundle包

调用的函数为:

public static AssetBundleManifest BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform)

这个函数的功能为将所有设置了资源标签的资源打出AssetsBundle包

函数一共有三个参数:

第一个参数为打包出来文件的路径

第二个参数为设置打包资源的压缩方式,是枚举变量,其中比较常用的三个为:

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

BuildAssetBundleOptions.None:使用LZMA算法压缩,压缩的包更小,但是加载时间更长,需要解压全部。
BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4压缩,压缩率没有LZMA高,但是我们可以加载指定资源而不用解压全部。

这几种压缩方式中,LZ4比较常用

第三个参数为设置打包资源的应用平台,一般都使用

BuildTarget.StandaloneWindows64 //PC端

BuildTarget.Android //安卓端

BuildTarget.iOS //苹果端

示例代码:

BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetBundle", BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);

调用函数改变资源标签

改变资源标签的方式,除了在Unity编辑器中设置之外,还可以使用代码设置资源标签

string path = "Assets/MainPrefab.prefab";
AssetImporter importer = AssetImporter.GetAtPath(path);
importer.assetBundleName = "prefab"
importer.assetBundleVariant = "u3d";

这里面应用到的类是AssetImporter类,这个类型代表了AssetBundole资源。

获取AssetImporter类型变量的方法为AssetImporter.GetAtPath(string)方法

这个方法的参数是传入一个由Assets开头,直到文件的后缀名结束的路径,然后将这个文件AssetsBundle相关属性的AssetImporter类返回

然后通过AssetImporter类的assetBundleName改变文件的资源标签

然后通过AssetImporter类的assetBundleVariant改变文件的资源版本标签


加载AssetBundle包

AssetBundle.LoadFromFile 本地资源加载

通过加载本地文件的形式加载AssetBundle资源,场景适用的情况下效率最高

AssetBundle ab = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundle/1.1");

在方法中传入本地资源路径,最后要以AssetBundle包的文件名和后缀名为止,将路径下的AssetBundle包以AssetBundle类型的变量保存下来

AssetBundle.LoadFromFileAsync 本地资源加载(异步)

上面方法的异步版本,在加载过程中不会因为包体过大导致程序进入未响应,需要用到协程(不会协程用法的自己去网上学一下,或者翻我以前的博客)

    IEnumerator LoadAssetBundle(Action<AssetBundle> action){AssetBundleCreateRequest creat = AssetBundle.LoadFromFileAsync(Application.dataPath + "/AssetBundle/1.1");yield return creat;AssetBundle ab = creat.assetBundle;action(ab);}

AssetBundle.LoadFromFileAsync方法参数与同步版本相同,不过返回值由AssetBundle类型变为了AssetBundleCreateRequest类型,这个类型的变量可以作为yield return等待方法的参数,然后通过assetBundle属性获取AssetBundle类型变量

AssetBundle.LoadFromMemory 从数据流加载

通过数据流读取AssetBundle资源,这个方法读取本地文件的效率不如LoadFromFile,所以不要用这个方法加载本地文件的AssetBundle,这个方法应该大部分应用于通过网络协议传输的数据流上

AssetBundle ab = AssetBundle.LoadFromMemory(File.ReadAllBytes(Application.dataPath + "/AssetBundle/1.1"));

方法的参数为byte数组,返回一个AssetBundle类型的变量

AssetBundle.LoadFromMemoryAsync 从数据流加载(异步)

上述方法的异步版本,通过数据流加载速度相对较慢,比较建议使用异步

    IEnumerator LoadAssetBundle(Action<AssetBundle> action){AssetBundleCreateRequest creat = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(Application.dataPath + "/AssetBundle/1.1"));yield return creat;AssetBundle ab = creat.assetBundle;action(ab);}

与LoadFromFileAsync方法相同,返回一个AssetBundleCreateRequest类型的参数,这个类型的变量可以作为yield return等待方法的参数,然后通过assetBundle属性获取AssetBundle类型变量

UnityWebRequestAssetBundle.GetAssetBundle 从网络获取(异步)

从网址下载AssetBundle包并读取,因为从网络下载的过程都较长,所以这个方法只有异步版本

    IEnumerator LoadAssetBundle(Action<AssetBundle> action){string url = "file://" + Application.dataPath + "/AssetBundle/1.1";UnityWebRequest unityAb = UnityWebRequestAssetBundle.GetAssetBundle(url);yield return unityAb.SendWebRequest();AssetBundle ab = DownloadHandlerAssetBundle.GetContent(unityAb);action(ab);}

方法需要传入一个网址作为参数,将这个参数中的内容下载下来,这里传入了一个本地路径,本地路径也可以作为网址传入,方法返回一个UnityWebRequest类型的变量,这个类型的变量中SendWebRequest方法可以返回一个能够在yield return中应用的值,使协程等待至文件下载完毕,然后通过DownloadHandlerAssetBundle.GetContent方法,传入UnityWebRequest类型的参数,就能够返回AssetBundle类型的变量


从AssetBundle包中获取资源

单纯只是读取到AssetBundle类型的变量是无法直接使用的,需要将AssetBundle类型转换为平时使用的资源类型,比如GameObject,Material。Texture类型

AssetBundle.LoadAsset<>() 从包中读取单个文件

AssetBundle ab = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundle/1.1");
GameObject a = ab.LoadAsset<GameObject>("Cube");

AssetBundle.LoadAsset<>()方法分别有一个泛型类型和一个参数,方法的泛型类型中传入需要从方法中获取的返回值类型,参数为需要获取的类型的名字,上面代码中表示返回AssetBundle包中名为Cube的预设物并保存

AssetBundle.LoadAssetAsync<>() 从包中读取单个文件(异步)

    IEnumerator LoadGameObject(AssetBundle ab , Action<GameObject> action){AssetBundleRequest abr = ab.LoadAssetAsync<GameObject>("Cube");yield return abr;GameObject g = (GameObject)abr.asset;action(g);}

与AssetBundle.LoadAsset<>()方法的泛型和参数应用方式相同,但是返回值为AssetBundleRequest类型,这个类型可以直接传入yield return,并且可以通过asset属性获取保存的资源,不过返回的资源是Object类型,需要进行强制转换

AssetBundle.LoadAllAssets 从包中获取全部文件

AssetBundle ab = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundle/1.1");
UnityEngine.Object[] objs = ab.LoadAllAssets();

AssetBundle.LoadAllAssets 不需要任何参数,返回一个Objcet数组,这个数组包含AssetBundle包中包含的全部资源

AssetBundle.LoadAllAssetsAsync 从包中获取全部文件(异步)

    IEnumerator LoadGameObject(AssetBundle ab , Action<UnityEngine.Object[]> action){AssetBundleRequest abr = ab.LoadAllAssetsAsync();yield return abr;UnityEngine.Object[] objs = ab.LoadAllAssets();action(objs);}

使用方式和LoadAssetAsync相同,只不过是改为了使用LoadAllAssets()方法返回Object数组


卸载AssetBundle资源包

AssetBundle.Unlock 卸载AssetBundle包

        AssetBundle ab = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundle/1.1");ab.Unload(true);

调用AssetBundle类型变量的Unload方法,就能够从内存中卸载AssetBundle包的资源,其中参数的布尔值为是否释放场景中正在使用的AssetBundle包中的资源,一般默认都会传入true作为参数,卸载AssetBundle包时,场景中有涉及到包内资源的物体会报错,所以一般在切换场景或特定情况下使用


http://www.mrgr.cn/p/01176877

相关文章

SQL217 对所有员工的薪水按照salary降序进行1-N的排名

示例: drop table if exists `salaries` ; CREATE TABLE `salaries` ( `emp_no` int(11) NOT NULL, `salary` int(11) NOT NULL, `from_date` date NOT NULL, `to_date` date NOT NULL, PRIMARY KEY (`emp_no`,`from_date`)); INSERT INTO salaries VALUES(10001,88958,2002-…

下载M3U8/Blob视频教程

准备工作: 以下操作默认为google浏览器,如微信中的视频提示“请在微信客户端打开链接”,则按如下设置微信客户端(默认浏览器设置为google浏览器) 1、安装”篡改猴“ 安装成功,其他插件安装方法类似。 2、打开视频网站播放视频,并下载

使用Files.walk删除文件

使用`Files.walk`删除指定文件名的文件。摘要:使用Files.walk删除指定文件名的文件。使用Files.walk工具,递归判断指定目录中的常规文件路径名是否符合约定名称,如果满足条件就删除。 public class DelFile {// 文件名在此集合就删除private static Set<String> given…

表情识别 | 卷积神经网络(CNN)人脸表情识别(Matlab)

表情识别 | 卷积神经网络(CNN)人脸表情识别&#xff08;Matlab&#xff09; 目录 表情识别 | 卷积神经网络(CNN)人脸表情识别&#xff08;Matlab&#xff09;预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab使用卷积神经网络(CNN)&#xff0c;进行人脸表情情绪识别…

LabVIEW轴承表面缺陷检测系统

LabVIEW轴承表面缺陷检测系统 为了解决轴承生产中人工检测效率低下、误检率高的问题&#xff0c;实现了一套基于LabVIEW的轴承表面缺陷自动检测系统。该系统利用工业相机采集轴承图像&#xff0c;通过图像处理技术对轴承表面的划痕缺陷和倒角缺陷进行自动识别和分析&#xff0…

Linux 环境下制作 deb 软件包

一、简介 前面的笔记中已经展示过了,怎么移植的一个工具境到 ARM 环境中,对于使用 buildroot 和 yocto 的朋友来说,此笔记就没有作用了,因为管理工具包会帮我们把这个工作处理了,就算需要自定义包操作方式也不一样,可以参考上一篇笔记。 而对于 ubuntu 这样的操作系统,虽…

【QA】Git的底层原理

前言 本文通过一个简单的示例&#xff0c;来理解Git的底层原理。 示例 1、新建本地仓库并上传第一个文件 相关步骤&#xff1a; 新建仓库及创建文件查看文件状态将文件添加到暂存区将文件提交到本地仓库 HMTeenLAPTOP-46U4TV6K MINGW64 /d/GSF_Data/Github/Java/Git/git-…

职场口才使人取得事业上的成功?

职场口才使人取得事业上的成功&#xff1f; 一、引言 在职场中&#xff0c;一个人的口才能力往往成为其事业成功的关键因素。优秀的职场口才不仅能够帮助我们更好地与他人沟通交流&#xff0c;还能够展现个人的专业素养和魅力&#xff0c;为事业的顺利发展奠定坚实基础。本文将…

力扣-419. 甲板上的战舰

1.题目 题目地址(419. 甲板上的战舰 - 力扣(LeetCode)) https://leetcode.cn/problems/battleships-in-a-board/ 题目描述 给你一个大小为 m x n 的矩阵 board 表示甲板,其中,每个单元格可以是一艘战舰 X 或者是一个空位 . ,返回在甲板 board 上放置的 战舰 的数量。 战舰…

有没有大佬知道这种数据应该怎么抓取呀?

大家好,我是Python进阶者。 一、前言 前几天在Python白银交流群【王者级混子】问了一个Python网络爬虫的问题。问题如下:有没有大佬知道这种数据应该怎么抓取呀?我鼠标移到上面才会出现的数据。二、实现过程 这里【Crazy】和【此类生物】给了一个指导。后来粉丝也查了下谷歌…

你的网站还在使用HTTP? 免费升级至HTTPS吧

如果您的网站还在使用老的http协议&#xff0c;可以申请一个免费的SSL证书升级至https&#xff01; 具体步骤如下&#xff1a; 1 申请免费SSL证书 根据你的需求选择合适的SSL证书类型&#xff0c;如单域名证书&#xff0c;多域名证书、通配符证书 登录免费供应商JoySSL官网&…

有意思!一个关于 Spring 历史的在线小游戏

发现 Spring One 的官网上有个好玩的彩蛋,分享给大家! 进到Spring One的官网,可以看到右下角有个类似马里奥游戏中的金币图标。点击该金币之后,会打开一个新的页面,进入下面这样一个名为:The History Of Spring 的在线小游戏你可以使用上下左右的方向键来控制Spring的Log…

店匠科技技术产品闪耀,引领新质生产力发展

在科技飞速发展的今天,新质生产力正成为推动社会进步和经济高质量发展的核心力量。店匠科技,作为一家致力于为全球B2C电商提供产品和技术解决方案的领先企业,其技术产品不仅体现了新质生产力的创新特质,更在推动电商行业转型升级中发挥了重要作用。 新质生产力,以创新为主导,摆…

原型链prototype、__proto、constructor的那些问题整理

再了解原型链之前,我们先来看看构造函数和实例对象的打印结构 - 函数 这里我们定义一个构造函数Fn,然后打印它的结构吧 function Fn(){} console.dir(Fn)控制台得到结构 从上面结构我们能看的出来,函数有两种原型,一种是作为函数特有的原型:prototype,另一种是作为对象的__…

【Linux】进程间通信(共享内存、消息队列、信号量)

一、System V —— 共享内存&#xff08;详解&#xff09; 共享内存区是最快的 IPC 形式。一旦这样的内存映射到共享它的进程的地址空间&#xff0c;这些进程间数据传递不再涉及到内核&#xff0c;换句话说&#xff0c;就是进程不再通过执行进入内核的系统调用来传递彼此的数…

3d合并的模型为什么没有模型---模大狮模型网

在3D建模中&#xff0c;合并模型是常见的操作&#xff0c;它可以将多个模型合并成一个整体。然而&#xff0c;有时候在合并后却发现部分模型消失了&#xff0c;这可能会让人感到困惑和失望。本文将探讨为什么合并的3D模型中会出现没有模型的情况&#xff0c;并提供一些解决方法…

React 《useEffect》

概念 useEffect是一个React Hook函数,用于在React组件中创建不是由事件引起而是由渲染本身引起的操作(副作用), 比 如发送AJAX请求,更改DOM等等:::warning 说明:上面的组件中没有发生任何的用户事件,组件渲染完毕之后就需要和服务器要数据,整个过程属于“只由渲染引起的…

SVN小乌龟汉化问题

1.首先确认中文语言包和SVN版本需要一致&#xff08;点击右键 选择最后一个选项即可查看&#xff09; 官网链接 点击这个官网链接可以下载对应版本的中文包 2.下载好之后直接无脑下一步安装即可 3.如果还是没有中文&#xff0c;找到这个文件夹&#xff0c;把里面的内容全部删…

Nessus 10.7 Auto Installer for Ubuntu 22.04 (updated Apr 2024)

Nessus 10.7 Auto Installer for Ubuntu 22.04 (updated Apr 2024)Nessus 10.7 Auto Installer for Ubuntu 22.04 (updated Apr 2024) 发布 Nessus 试用版自动化安装程序,支持 macOS Sonoma、RHEL 9 和 Ubuntu 22.04 请访问原文链接:https://sysin.org/blog/nessus-auto-inst…