Unity开发——编辑器打包、3种方式加载AssetBundle资源

一、创建ab资源

(一)Unity资源设置ab格式
1、选中要打包成assetbundle的资源;

可以是图片,材质球,预制体等,这里方便展示用预制体打包设置展示;

2、AssetBundle面板说明
(1)初始面板

点击资源的Inspector面板最下面AssetBundle选项按钮,会弹出AssetBundle面板;

AssetBundle选项面板如下,默认两个位置都是None;设置输入后,按回车键确认;

在左边名称设置里有按钮选项,可一键清除不用的、弃用的名称和后缀。

输入的英文字母,即使是大写也会自动转为小写;所以不用考虑大小写问题;

(2)设置面板

从左往右

第一个设置,表示资源打包后在AB文件夹里的资源名,可设置多层级目录;

第二个设置,表示资源打包后的后缀名,同资源名都可以自定义设置无格式要求。

1)                           fish        image        表示在AB文件夹里生成一个fish.image资源;

2)        video/play/dead        music        表示在AB文件下里生成一个video文件夹,在video文件夹里生成一个play文件夹,在play文件夹里生成一个dead.music资源;

 3、关于资源名称,ab包名称和加载路径说明 

上面和下面两张图结合着看;

(1)资源信息与所在位置

unity里名为Fish的预制体,生成的ab资源名为prefab.imaged,

文件所在的地址是:.../装有ab资源的文件夹/ab/prefab.image;

(2)获取资源及所需信息

加载ab资源的地址是:path = .../装有ab资源的文件夹/ab/prefab.image;

AssetBundle ab = AssetBundle.LoadPath(path);

获取ab包里的某一资源是:resourceName = Fish        (注意,不是prefab.image!!!)

GameObject obj = ab.LoadAsset(resourceName);

(二)编辑器工具栏打包
1、Editor文件夹

编辑器功能的脚本要放到专门的Editor文件夹下,普通脚本正常放在Scripts文件夹下;

初始项目中不存在,同Resource文件夹,自己新建一个即可。

关于Unity一些特殊文件夹,可以看我其他博文,有博文介绍讲解;

2、自定义打包设置

打包生成ab资源的脚本CreateABpack里,打包功能按钮自定义放在File文件下,如下图;

打包功能的按钮名自定义为Build AssetBundles;可根据需求自己选择设置放置;

3、功能使用

非项目运行状态下,点击下图的Build AssetBundles按钮,即可打包项目中所有设置了ab设置的资源;

(三)C#生成ab包的脚本
1、相关库

使脚本在编辑器环境下可直接,需使用UnityEditor库;

在指定文件夹下存放生成的ab资源,需要使用System.IO库;

using UnityEditor;          //把该脚本当工具使用,使脚本在编辑器模式下就可以运行
using System.IO;            //文件使用相关的库
2、自定义按钮名称和位置

使用特性:[MenuItem("显示在工具栏哪个文件夹下/该打包方法在菜单上显示的名称")]

用静态方法,使可用全局访问,实现非运行状态下也可以调用使用;

[MenuItem("File/Build AssetBundles")]    //方法做到File下,按钮名为Build AssetBundles
static void BuildAllAssetBundles(){}     //静态方法,全局可以访问
3、打包资源 

自定义打包后的输出路径:

//相对路径,打包到工程里与Asset同级的AB_File文件夹下,不是Asset文件夹里的AB_File文件夹下
string path = "AB_File"; //绝对路径,打包到指定文件夹,C盘下面的AB_File文件夹下
string file = @"C:\AB_File";                

可能存在输出的文件夹不存在,先判断文件夹存不存在,不存在则在目标位置生成目标文件夹。

if (Directory.Exists(filePath) == false)    //判断目标文件夹/相对路径是否存在Directory.CreateDirectory(file);        //相对路径不存在/目标文件夹不存在,则创建

使用API:BuildPipeline.BuildAssetBundles(输出文件地址,ab资源压缩格式,输出平台)

设置打包格式,具体参数自行查看api;

//资源打包,参数:打包到的指定文件夹的路径,压缩方式,输出平台
BuildPipeline.BuildAssetBundles(filePath, BuildAssetBundleOptions.None,BuildTarget.StandaloneWindows64);
4、功能代码
using UnityEditor;
using System.IO;public class CreateABpack
{[MenuItem("File/Build AssetBundles")]static void BuildABundles(){//string filePath = "AssetBundlesFile";string filePath = @"C:\AB_File";if (Directory.Exists(filePath) == false)Directory.CreateDirectory(filePath);BuildPipeline.BuildAssetBundles(filePath, BuildAssetBundleOptions.None,BuildTarget.StandaloneWindows64);}
}

二、3种ab包加载方式

(一)本地直接加载:LoadFromFile
1、方法说明
(1)AssetBundle ab = AssetBundle.LoadFromFile(filePath);

这是加载 AssetBundle 的最快方法。

同步加载中,将等待 AssetBundle 对象创建完毕才返回。

在主线程中执行,若资源过大,加载创建时间过长,则建议使用异步加载。

FilePath是文件在磁盘上的路径,可支持相对路径(相对项目,文件在项目中的路径位置)。

(2)T asset= ab.LoadAsset<T>(resName); 

从ab包里加载资源,资源目标格式为T;如Texture,GameObject等;
resName是资源在Unity中的资源名.    如:Fish

//从文件中加载AssetBundle,文件路径,一直到ab资源名后缀结束
//如:C:\AB_File\ab\prefab.imageAssetBundle.LoadFromFile(FilePath);    //从ab包里加载资源,资源目标格式为T;
//resName是资源在Unity中的资源名.    如:FishT asset= ab.LoadAsset<T>(resName);     
2、对应的异步加载API

AssetBundle.LoadFromFileAsync();

3、其他同步加载方式

AssetBundle.LoadFromMemory;AssetBundle.LoadFromStream;

4、功能代码
using System.Collections.Generic;
using UnityEngine;public class LoadABpack : MonoBehaviour
{private string localFile = @"C:\AB_File\";public static Dictionary<string, GameObject> prefabDic = new Dictionary<string, GameObject>();public void ClickBut(){LoadResource(localFile + @"ab\prefab.image", "Fish");}/// <summary>/// 直接加载本地ab包/// </summary>/// <param name="resName"></param>/// <param name="filePath"></param>public void LoadResource(string filePath, string resName){if (!prefabDic.ContainsKey(resName)){AssetBundle ab = AssetBundle.LoadFromFile(filePath);GameObject obj = ab.LoadAsset<GameObject>(resName);prefabDic.Add(resName, obj);ab.Unload(false);}UsingResource(resName);}public void UsingResource(string resName){if (prefabDic.ContainsKey(resName)) Instantiate(prefabDic[resName]);else Debug.Log("No AssetBundles");}
}
(二)本地异步加载:LoadFromFileAsync
1、方法说明
(1)AssetBundleCreateRequest abRequest = AssetBundle.LoadFromFileAsync(filePath);

声明的是AssetBundleCreateRequest类型,不是AssetBundle类型!!!

注意与同步加载的方法进行对比比较;

(2)使用异步协程方法实现

一般使用协程执行;需要使用到using System.Collections;库

对于协程,不能使用静态方法调用,即调用协程的方法不能是static修饰的;

//这种是错误的
public static void ClickBut()
{StartCoroutine(Asyn_LoadAB(localFile, resName));
}//这样才正确使用
public void ClickBut()
{StartCoroutine(Asyn_LoadAB(localFile, resName));
}//协程实现异步加载ab资源
IEnumerator Asyn_LoadAB(string filePath, string resName)
{//注意声明的类型!!!AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(filePath);yield return request;AssetBundle ab = request.assetBundle;T res = ab.LoadAsset<T>(resName);
}
2、对应的同步加载API

AssetBundle.LoadFromFile(FilePath);  

3、其他异步加载方式

AssetBundle.LoadFromMemoryAsync;AssetBundle.LoadFromStreamAsync;

4、功能代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class LoadABpack : MonoBehaviour
{private string localFile = @"C:\AB_File\";public static Dictionary<string, GameObject> prefabDic = new Dictionary<string, GameObject>();public void ClickBut(){StartCoroutine(Asyn_LoadAB(localFile + @"ab\prefab.image", "Fish"));}/// <summary>/// 异步加载本地AB包/// </summary>/// <param name="resName"></param>/// <param name="filePath"></param>IEnumerator Asyn_LoadAB(string filePath, string resName){if (!prefabDic.ContainsKey(resName)){AssetBundleCreateRequest abRequest = AssetBundle.LoadFromFileAsync(filePath);yield return abRequest;AssetBundle ab = abRequest.assetBundle;GameObject obj = ab.LoadAsset<GameObject>(resName);//加载资源yield return obj != null;prefabDic.Add(resName, obj);//存储资源ab.Unload(false);}UsingResource(resName);}public void UsingResource(string resName){if (prefabDic.ContainsKey(resName)) Instantiate(prefabDic[resName]);else Debug.Log("No AssetBundles");}
}
(三)服务器异步加载:UnityWebRequest 
1、方法说明

注意!!!

(1)正确使用

UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(filePath);

AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);

(2)错误使用1

UnityWebRequest request = UnityWebRequest.Get(url);

AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);        //报转化格式无效

(3)错误使用2

UnityWebRequest request = UnityWebRequest.Get(url);

AssetBundle ab =(request.DownloadHandler as DownloadHandler).assetbundle; //结果是ab= null

2、特别说明:
(1)静态类使用UnityWebRequest

静态类UnityWebRequest.Get创建的Request,自带DownloadHandler和UploadHandler;

UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(filePath);
yield return request.SendWebRequest(); 
AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);或UnityWebRequest request = UnityWebRequest.Get(url);
yield return request.SendWebRequest();
string strData = request.downloadHandler.text;
(2)构造函数使用UnityWebRequest

构造函数new UnityWebRequest 创建的Request,没有的,需要自己手动创建赋值!!!

UnityWebRequest request =new UnityWebRequest(uri); 
DownloadHandlerFile download = new DownloadHandlerFile();
request.downloadHandler = download;
yield return request.SendWebRequest();
3、UnityWebRequest其他方法

除了获取服务器数据的Get方法,还支持Post,Put,Abort,Head方法

Get:一般用于向服务器获取信息;但Get访问时有信息暴露的风险;

Post:获取服务器信息,但Post访问时内容不会暴露,安全性更高;

Put:将数据发送到远程的服务器。比如文件上传;

Abort:会尽快结束联网,可以随时调用此方法。

方法调用后,如果 UnityWebRequest未完成,那么将会尽快停止上传或下载数据;

head: 只请求页面的首部;与Get方法几乎是一样;

Head使用时会检查超链接的有效性;检查网页是否被修改;

该方法多用于自动搜索机器人获取网页的标志信息,获取rss种子信息,或者传递安全认证信息等

3、其他服务器加载方式

WWW方式:        WWW request= new WWW(url);        但现在Unity已经弃用。

4、功能代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;public class LoadABpack : MonoBehaviour
{private string localhost = @"http://localhost/AB_File/";public static Dictionary<string, GameObject> prefabDic = new Dictionary<string, GameObject>();public void ClickBut(){StartCoroutine(LoadSeverResource(localhost + @"ab\prefab.image", "Fish"));}/// <summary>/// 异步获取服务器上ab资源/// </summary>/// <param name="resName"></param>/// <param name="filePath"></param>/// <returns></returns>IEnumerator LoadSeverResource(string filePath, string resName){if (!prefabDic.ContainsKey(resName)){UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(filePath);yield return request.SendWebRequest();AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);GameObject obj = ab.LoadAsset<GameObject>(resName);yield return obj;prefabDic.Add(resName, obj);ab.Unload(false);}UsingResource(resName);}public void UsingResource(string resName){if (prefabDic.ContainsKey(resName)) Instantiate(prefabDic[resName]);else Debug.Log("No AssetBundles");}
}

三、补充说明及相关报错解决

(一)UnityWebRequest获取不同资源数据使用方法会不同;

关于服务器获取数据,详见可查看本人另一篇服务器获取xlua文件数据的博文;

关于数据解析,以及Json格式数据处理及相关Json插件使用,也有对应的博文欢迎查看;

(二)重新再次加载ab包,出现报错

The AssetBundle can't be loaded because another AssetBundle with the same files is already loaded.

1、加载使用完ab包,没有及时卸载;(出现该报错,基本是这个原因)

ab包加载后要卸载,不卸载再次执行加载同一个ab包时,会出现上述报错;

如:我在主游戏场景中加载ab资源,然后跳转回开始场景,然后再运行到主游戏场景,

由于之前主场景运行加载的ab资源没有卸载,这次再运行主场景,就会报该错误。

解决方法:

在加载ab资源后卸载ab包,注意加载完再后卸载,不然容易出现找不到ab资源问题。

AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
GameObject obj = ab.LoadAsset<GameObject>(resName);
yield return obj;//等待资源获取完成,卸载ab
ab.Unload(false);
2、服务器获取ab包和解析ab包是同一帧。

有时候获取如UI资源,刚获取到资源,相应文件还处于打开中缓存在内存中,此时Unity检测到已获取资源,立即执行解析使用资源操作,但因内存中还存在打开的ab文件的文件,被认为相同文件已经被打开加载,故报上述错误。

解决方法:

在获取/下载外部资源的文件系统释放后,再调用解析资源的方法;可在调用解析方法前加上yield return new WaitForSeconds(0.1f);

AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);yield return new WaitForSeconds(0.1f);GameObject obj = ab.LoadAsset<GameObject>(resName);

该解决方法参考了原文:The AssetBundle ‘xxx‘ can‘t be loaded because another AssetBundle with the same_can't be loaded because another assetbundle with t-CSDN博客

AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
yield return new WaitForSeconds(0.1f);
GameObject obj = ab.LoadAsset<GameObject>(resName);
3、ab包资源设置的名称相同

资源名相同,后缀不同的单个资源是允许的;但是名相同,后缀相同,即使路径不同也会报错;

解决方法:

生成ab资源时,注意资源名与资源后缀的设置,不要有重复命名;

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

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

相关文章

【YOLOv5进阶】——模型结构与模型原理YOLOv5源码解析

一、基础知识 1、backbone backbone是核心组成部分&#xff0c;主要负责提取图像特征。具体来说&#xff0c;backbone通过一系列的卷积层和池化层对输入图像进行处理&#xff0c;逐渐降低特征图的尺寸同时增加通道数&#xff0c;从而保留和提取图像中重要的特征。这些提取出的…

Unity3D获得服务器时间/网络时间/后端时间/ServerTime,适合单机游戏使用

说明 一些游戏开发者在做单机游戏功能时&#xff08;例如&#xff1a;每日奖励、签到等&#xff09;&#xff0c;可能会需要获得服务端标准时间&#xff0c;用于游戏功能的逻辑处理。 问题分析 1、自己如果有服务器&#xff1a;自定义一个后端API&#xff0c;客户端按需请求…

使用Obfuscar 混淆WPF(Net6)程序

Obfuscar 是.Net 程序集的基本混淆器&#xff0c;它使用大量的重载将.Net程序集中的元数据&#xff08;方法&#xff0c;属性、事件、字段、类型和命名空间的名称&#xff09;重命名为最小集。详细使用方式参见&#xff1a;Obfuscar 在NetFramework框架进行的WPF程序的混淆比较…

Spring @Transactional 事务注解

一、spring 事务注解 1、实现层(方法上加) import org.springframework.transaction.annotation.Transactional;Transactional(rollbackFor Exception.class)public JsonResult getRtransactional() {// 手动标记事务回滚TransactionAspectSupport.currentTransactionStatus…

抖店入驻门槛,一降再降,2024年商家入驻抖店最佳的时机来了!

大家好&#xff0c;我是电商糖果 抖店已经发展有四年多的时间了&#xff0c;现在也算是比较成熟的电商平台. 这几年因为直播带货的火爆&#xff0c;再加上抖音的流量支撑&#xff0c;还有抖音在背后的扶持和推广。 让抖店成了电商行业的黑马项目&#xff0c;吸引了不少商家入…

ACWC:Worst-Case to Average-Case Decryption Error

参考文献&#xff1a; [LS19] Lyubashevsky V, Seiler G. NTTRU: Truly Fast NTRU Using NTT[J]. IACR Transactions on Cryptographic Hardware and Embedded Systems, 2019: 180-201.[DHK23] Duman J, Hvelmanns K, Kiltz E, et al. A thorough treatment of highly-efficie…

[element-ui]el-form自定义校验-图片上传验证(手动触发部分验证方法)

背景&#xff1a; 在做导入文件功能的时候&#xff0c;需要校验表单&#xff0c;如图所示 店铺字段绑定在表单数据对象上&#xff0c;在点击确定的时候正常按照表单验证规则去校验&#xff0c;就不再赘述。 文件上传是个异步过程&#xff0c;属性值改变后不会去触发验证规则…

智能管理,无忧报修——高校校园报事报修系统小程序全解析

随着数字化、智能化的发展&#xff0c;高校生活也迎来了前所未有的变革。你是否还在为宿舍的水龙头漏水、图书馆的灯光闪烁而烦恼&#xff1f;你是否还在为报修流程繁琐、等待时间长而焦虑&#xff1f;今天&#xff0c;这一切都将成为过去式&#xff01;因为一款震撼高校圈的新…

【QT5】<总览一> QT环境搭建、快捷键及编程规范

文章目录 前言 一、简单介绍QT 二、安装QT Creator 三、第一个QT项目 四、常用快捷键 五、QT中的编程规范 前言 在嵌入式Linux应用层开发时&#xff0c;经常使用QT作为图形化界面显示工具。为学习Linux下的QT编程&#xff0c;在Ubuntu和开发板中搭建QT开发环境&#xff…

TMS320F280049 ECAP模块--应用(2)

例1-上升沿触发 如下图所示&#xff0c;evt1-4设置为上升沿触发&#xff0c;在每个上升沿ctr值依次加载到cap1-4. 例2-上升下降沿触发 每个边沿都可选为事件&#xff0c;每次事件到来&#xff0c;依次把ctr加载到cap1-4。 例3-差异模式下上升沿触发 差异模式下每次事件到来时…

Qt_C++ RFID网络读卡器Socket Udp通讯示例源码

本示例使用的设备&#xff1a; WIFI/TCP/UDP/HTTP协议RFID液显网络读卡器可二次开发语音播报POE-淘宝网 (taobao.com) #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QHostInfo> #include <QNetworkInterface> #include <…

PyQt5串口测试工具

笔者经常会遇到使用上位机进行相关测试的场景&#xff0c;但现成的上位机并不能完全满足自己的需求&#xff0c;或是上位机缺乏使用说明。所以&#xff0c;自己写&#xff1f; 环境说明 pycharm 2023.2.25 python 3.10 anaconda 环境配置 conda create -n envsram ##…

学生信息管理系统C++

设计目的 使学生进一步理解和掌握课堂上所学的面向对象C编程知识&#xff0c;巩固和加深学生对C面向对象课程的基本知识的理解和掌握。掌握C面向对象编程和程序调试的基本技能&#xff0c;学会利用C语言进行基本的软件设计&#xff0c;着重提高运用C面向对象语言解决实际问题的…

Go Modules 使用

文章参考https://blog.csdn.net/wohu1104/article/details/110505489 不使用Go Modules&#xff0c;所有的依赖包都是存放在 GOPATH /pkg下&#xff0c;没有版本控制。如果 package 没有做到完全的向前兼容&#xff0c;会导致多个项目无法运行(包版本需求不同)。 于是推出了g…

秋招突击——第四弹——Java的SSN框架快速入门——Spring(2)

文章目录 前言其他Spring加载properties 容器创建容器获取beanBeanFactory容器总结 注解注解开发对定义bean纯注解开发Bean管理Bean作用范围Bean生命周期 注解开发依赖注入第三方bean管理第三方bean管理第三方bean注入 注解开发总结 Spring整合整合mybatis整合Junit AOPAOP核心…

【C、C++编译工具】CLion工具介绍与安装

一、问题 最近突发奇想想学学最开始接触的语言C&#xff0c;之前大学的时候用的更多的工具还是VC&#xff0c;工作后慢慢接触了CLion&#xff0c;跟pycharm其实差不多&#xff0c;都是集成开发环境&#xff08;IDE&#xff09; 解释&#xff1a;什么是 IDE&#xff1f; 根据计…

2024年5月 | deepin 深度应用商店-应用更新记录

新增应用 序号应用名称deepin 系统版本应用分类应用类型1HitPaw Watermark Removerdeepin V23图形图像wine2PDF to DOCX转换器deepin V23网络应用linux3天工 AIdeepin V20.9效率办公linux4稻壳阅读deepin 20.9 deepin V23效率办公linux5讯飞星火deepin V20.9效率办公linux6文…

扩散模型的技术原理和应用价值

引言 一、扩散模型的基本概念 扩散模型(Diffusion Models)是一种基于概率论的生成模型&#xff0c;最初源自物理学中的扩散过程理论&#xff0c;比如墨水在水中的扩散过程。在机器学习领域&#xff0c;这一概念被创造性地应用于数据生成任务&#xff0c;特别是图像和声音的合成…

Proxmox Backup Server 命名空间使用

作者&#xff1a;田逸&#xff08;formyz&#xff09; Proxmox Backup Server&#xff08;一下统称PBS&#xff09;从2.2版本开始&#xff0c;新增了命名空间这样一个功能。这个功能大大便利了多Proxmox VE集群或者单节点备份&#xff0c;在以前PBS版本中&#xff0c;如果有多个…

HTML旋转照片盒子

效果图 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compatible" content…