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.image

AssetBundle.LoadFromFile(FilePath);    

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

T 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资源时,注意资源名与资源后缀的设置,不要有重复命名;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【React篇】组件错误边界处理(组件错误引起的页面白屏)

我们知道在生产环境react错误会导致整个页面崩溃&#xff0c;显示为空白页面。 比如下图的错误&#xff0c;导致了左侧页面直接白屏&#xff1a; 由于某一个组件报错导致整个页面崩溃是很严重的问题&#xff0c;那么我们应该如何去降低代码报错带来的影响呢&#xff1f; 我们…

JavaScript 动态网页实例 —— 窗口控制

除了打开和关闭窗口之外,还有很多其他控制窗口的方法。例如,可以使用 window.focus()方法使窗口获得焦点,也可以利用与其相对的window.blur 方法使窗口失去焦点。本节介绍移动窗口、改变窗口大小、窗口滚动、窗口超时操作、常用窗口事件、常用窗口扩展等窗口控制的方法和手段。…

mac电脑鼠标键盘共享软件:ShareMouse for Mac 激活版

ShareMouse 是一款跨平台的键盘和鼠标共享软件&#xff0c;它允许用户在多台计算机之间共享同一组键盘和鼠标&#xff0c;实现无缝的操作和控制。该软件适用于 Windows 和 macOS 系统&#xff0c;并且支持多种连接方式&#xff0c;包括局域网连接和无线连接。 使用 ShareMouse&…

从openstack环境中将服务器镜像导出的简单办法

1 登录openstack的页面&#xff0c;找到计划导出的主机信息。 通过实例名称&#xff0c; IP地址&#xff0c;找到对应的记录。点击实例名称&#xff0c;进入详情页。 在这里主要可以知道&#xff0c;当前主机在服务器上的文件ID&#xff0c;可以按这个ID去找对应的目录。 还可…

java读取文件内容(正则表达式匹配)

已知文件score.txt内容如下&#xff1a; 语文85分&#xff0c;数学89分&#xff0c;英语75分&#xff0c;马列95分。 要求解析出其中的成绩数据&#xff0c;并计算总成绩 import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import jav…

JDK环境配置、安装

DK环境配置&#xff08;备注&#xff1a;分32位与64位JDK&#xff0c;32位电脑只能按照32位JDK&#xff0c;64位电脑兼容32、64位JDK&#xff09; 一、检查自己电脑是否安装过JDK 1.在电脑屏幕左下角&#xff0c;输入命令提示符CMD&#xff0c;打开命令提示符应用 2.在打开界…

QT系列教程(7) QLineEdit介绍

简介 QLineEdit属于输入插件&#xff0c;用来实现单行录入。支持几种录入模式。 Normal表示正常录入,录入的信息会显示在QLineEdit上。 Password表示密码录入的方式&#xff0c;录入的信息不显示QLineEdit&#xff0c;只是通过黑色圆点显示。 NoEcho 表示不显示录入信息&am…

“开源与闭源:AI大模型发展的未来之路“

文章目录 每日一句正能量前言数据隐私开源大模型与数据隐私闭源大模型与数据隐私数据隐私保护的共同考虑结论 商业应用开源大模型的商业应用优势&#xff1a;开源大模型的商业应用劣势&#xff1a;闭源大模型的商业应用优势&#xff1a;闭源大模型的商业应用劣势&#xff1a;商…

ros DWA局部规划模块

ROS-DWA模块 主要流程DWAPlannerROS::computeVelocityCommandsDWAPlannerROS::dwaComputeVelocityCommandsDWAPlanner::findBestPathSimpleScoredSamplingPlanner::findBestTrajectory 调参技巧DWA被目标点过度吸引&#xff0c;且不听全局规划器指挥 消融实验goal_front_costs_…

Java 异步编编程——Java内置线程池(Executor 线程池)

文章目录 知道线程池是什么以及解决什么问题Java 内置线程池Java 内置线程池设计结构及执行机制ThreadPoolExecutor 中的概念生命周期核心参数阻塞队列4 种任务拒绝策略 线程池使用场景 知道线程池是什么以及解决什么问题 线程池&#xff08;Thread Pool&#xff09;是一种基于…

Kafka Java API

1、增加依赖 <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>1.0.0</version> </dependency>2、三个案例 案例1&#xff1a;生产数据 import org.apache.kafka.clients.p…

SpringBoot HelloWorld 之 实现注册功能

SpringBoot HelloWorld 之 实现注册功能 一.配置 创建数据库big_event CREATE TABLE user (id int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT ID,username varchar(20) COLLATE utf8_unicode_ci NOT NULL COMMENT 用户名,password varchar(32) COLLATE utf8_unicode_ci …

β-烟酰胺单核苷酸(NMN)功能不断得到验证 市场规模呈增长态势

β-烟酰胺单核苷酸&#xff08;NMN&#xff09;功能不断得到验证 市场规模呈增长态势 β-烟酰胺单核苷酸&#xff08;β-Nicotinamide mononucleotide&#xff0c;NMN&#xff09;是一种生物活性分子&#xff0c;是一种辅酶Ⅰ&#xff08;NAD&#xff09;的前体&#xff0c;也是…

WPF Binding对象

在WinForm中&#xff0c;我们要想对控件赋值&#xff0c;需要在后台代码中拿到控件对象进行操作&#xff0c;这种赋值形式&#xff0c;从根本上是无法实现界面与逻辑分离的。 在WPF中&#xff0c;微软引入了Binding对象&#xff0c;通过Binding&#xff0c;我们可以直接将控件与…

NTFS磁盘格式读写工具:Tuxera NTFS 2021 for Mac

Tuxera NTFS 是一款用于 macOS 系统的 NTFS 文件系统驱动程序。NTFS 是 Windows 系统中常用的文件系统&#xff0c;而 macOS 默认只支持读取 NTFS 格式的磁盘&#xff0c;不能进行写入操作。因此&#xff0c;如果你需要在 macOS 上进行 NTFS 磁盘的写入操作&#xff0c;就需要安…

php使用openssl返回false报错0308010C

本地php使用openssl返回false, 但是在服务器上测试正常openssl_encrypt($jsonStr, DES-ECB, $key, OPENSSL_RAW_DATA, ); 查看错误 openssl_error_string(); error:0308010C:digital envelope routines::unsupported 原因是: 服务器上的openssl是1.1版本, 本地是3.0版本 通…

真北5月小结|物事人心向上

1、跑步 今年的计划是每月跑15小时。五月实际跑了13小时17分。一到五月共跑了74小时43分&#xff0c;所以按平均每月15小时&#xff0c;还欠17分&#xff0c;六月补上。 另外两个跑步的标准是&#xff1a;保持跑步三天可见&#xff0c;最近龙舟雨&#xff0c;对这一条干扰很大&…

iframe内嵌网页自适应缩放 以展示源网页的比例尺寸

需求:这是我最近开发的低代码平台遇到的需求 ,要求将配置好的应用在弹框中预览(将预览网页内嵌入弹框中) 但是内嵌进入后 他会截取一部分(我源网站网页尺寸 是1980x1080 或者 3060X2160等等) 但是我这个dialog弹框只有我自定义的1000多px的宽高 他只会展示我iframe网页的一部分…

k8s之PV、PVC

文章目录 k8s之PV、PVC一、存储卷1、存储卷定义2、存储卷的作用2.1 数据持久化2.2 数据共享2.3 解耦2.4 灵活性 3、存储卷的分类3.1 emptyDir存储卷3.1.1 定义3.1.2 特点3.1.3 用途3.1.4 示例 3.2 hostPath存储卷3.2.1 定义3.2.2 特点3.2.3 用途3.2.4 示例 3.3 NFS存储卷3.3.1 …

BioVendor—sHLA-G ELISA试剂盒

人类白细胞抗原-G (HLA-G)与其他MHC类基因的不同之处在于它的低多态性和产生七种HLA-G蛋白的选择性剪接&#xff0c;这些蛋白的组织分布局限于正常的胎儿和成人组织&#xff0c;这些组织对先天和后天免疫细胞都具有耐受性。可溶性HLA-G是一种免疫抑制分子&#xff0c;诱导活化的…