大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

这几天在研究AssetBundle资源打包盒解析加载,也踩过很多坑,参考过很多人的文章

发现很多人关于AssetBundle的文章不是API过时了不能用,就是有点乱

也不是有点乱,就是摸不着头脑,让人不能快速的get到这个东西如何使用

所以我特意在踩过坑之后把我这个学到的经验分享给大家。


PS: 一把辛酸泪


二、参考文章

1.雨松大大的​​Unity3D研究院之Assetbundle的实战(六十三)​

2.​​Unity AssetBundle爬坑手记​

3.​​Unity5自动命名Assetbundle并打包​

4.​​5.0后版本的AssetBundle 使用​

5.​​Unity AssetBundle爬坑手记​

6.​​再详细的介绍一下Unity5的AssetBundle​

7.​​ Unity3D研究院之Assetbundle的实战(六十一)​

8.​​Unity5 新AssetBundle打包方式 BuildPipeline.BuildAssetBundles​

9.​​Unity最新版打包AssetBundle和加载的方法​

10.​​Unity中 BundleAsset资源的打包和解析加载​


PS:从参考的文章就知道踩了多少坑了



三、AssetBundle打包方式

3.1 API

  1. BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform);
  2. BuildAssetBundles(string outputPath,AssetBundleBuild[] builds,BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform);

3.2 参数说明

outputPath:包Bundle后存储的目录,如:Assets/AssetBundles,这个文件夹不会自动创建,如果它不存在的话,函数将会失败

BuildAssetBundleOptions:Bundle打包方式,none没有任何特殊选项,UncompressedAssetBundle在构建Bundle时不要压缩数据等等

BuildTarget:构建平台,如iphone,windows,android等

AssetBundleBuild[]:这个类与BuildAssetBundles一起使用。指定一个Bundle包的名称assetBundleName和它将包含的资源(如多张图片、音频等)的名称。

被传递给函数的AssetBundleBuild[]元素数组被称为“构建映射”,并作为指定编辑器包内容的替代方法。

AssetBundleBuild[]变量:

addressableNames:返回所有的addressableName数组

assetBundleName:AssetBundle的名字

assetBundleVariant:AssetBundle的扩展名如.unity

AssetBundle:指定属于一个addressableName名字的所有资源名字,是一个数组,也就是一个addressableName名字下包含的所有资源名字

3.3 例子

  1. 新建一个脚本PackBundles.cs,放到Editor文件夹中
    【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity资源打包与下载
  2. 编辑代码
    【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity打包与解析_02
    源代码:
using System.Collections.Generic;
using System.IO;
using UnityEditor;

public class PackBundles : Editor
{
//选定资源打包
[MenuItem("PackBundles/PackBundles")]
static void PutBundleAssetes()
{
//初始化一个AssetBundleBuild表
List<AssetBundleBuild> buildMap = new List<AssetBundleBuild>();
AssetBundleBuild build = new AssetBundleBuild();
//设置AssetBundleBuild的名字和资源路径
build.assetBundleName = "123.unity3d";
build.assetNames = new[] { "Assets/Textures/123.jpg" };
//添加进表
buildMap.Add(build);

//将这些资源包放在一个名为ABs的目录下
string assetBundleDirectory = "Assets/ABs";
//如果目录不存在,就创建一个目录
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}
//资源打包
BuildPipeline.BuildAssetBundles(assetBundleDirectory, buildMap.ToArray(), BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
}

//全部打包
[MenuItem("PackBundles/AllPackBundles")]
static void PutBundleAssetesAll()
{
//将这些资源包放在一个名为ABs的目录下
string assetBundleDirectory = "Assets/ABs";
//如果目录不存在,就创建一个目录
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory,BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
}
}

3.运行

首先Textures文件夹中存放一张123.jpg的图片

【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity服务器下载模型_03

【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_AssetBundle_04

点击PackBundles

【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity服务器下载模型_05

这就将Texture中的123.jpg打包到123.unity3d中了

第二种,全部打包AllPackBundles

需要先在编辑器设置好参数

【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity服务器下载模型_06【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity服务器下载模型_07

【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity服务器下载模型_08

然后打包

【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity服务器下载模型_09

这就将名字为Cube的预制体打包进入cube.unity3d

四、AssetBundle解析加载

4.1 API讲解

4.1.1 加载AssetBundle的API

【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity服务器下载模型_10

【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity打包与解析_11

//加载AssetBundle包

public static AssetBundle LoadFromFile(string path );

public static AssetBundle LoadFromFile(string path ,uint crc = 0);

public static AssetBundle LoadFromFile(string path ,uint crc = 0, ulong offset= 0);

4.1.2 参数说明

path: 读取AssetBundle的目录

crc : 校验用参数

offset: 这个值指定从哪里开始读取AssetBundle

//从网上加载AssetBundle包

public static UnityWebRequest GetAssetBundle(string uri, uint crc);

public static UnityWebRequest GetAssetBundle(string uri, uint version, uint crc);

public static UnityWebRequest GetAssetBundle(string uri, Hash128 hash, uint crc);

public static UnityWebRequest GetAssetBundle(string uri, CachedAssetBundle cachedAssetBundle, uint crc);

4.1.3 参数说明

uri:AssetsBundle包的网络地址:(可以是本地file:)

crc:0如果不为0,将会进行校验

version:一个整数版本号

hash:一个版本散列

cachedAssetBundle:用于将给定版本的AssetBundle下载到自定义缓存路径的结构

4.2 加载包中资源API

//加载AssetBundle包的资源

public Object LoadAsset(string name);

public Object LoadAsset( string name, Type type);

public T LoadAsset( string name);

public Object[] LoadAllAssets( Type type);

public Object[] LoadAllAssets();

public T[] LoadAllAssets();

public Object LoadAllAssetsAsync();

public Object LoadAssetAsync( string name);

4.2.1 参数说明

name:从AssetBundle包中加载名字为name的资源,返回object

Type:加载包内所有类型为type的资源

LoadAllAssets:加载包中所有资源

LoadAssetAsync: 异步加载包中所有资源

4.3 其他API

Path.Combine(string, string) 连接两个字符串

Application.streamingAssetsPath输出

E:/UnityProject/ARVR/Workspace/MyCharacter/Assets/StreamingAssets

Application.dataPath输出

E:/UnityProject/ARVR/Workspace/MyCharacter/Assets

4.2 从网上下载资源

【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity打包与解析_12

源代码:

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

public class LoadBundles : MonoBehaviour
{
GameObject go;
void Start()
{
StartCoroutine(Load());
}

IEnumerator Load()
{
//从远程服务器上进行下载和加载
WWW www = new WWW("ftp://123.778.1.128/cube.unity3d");
//等待文件下载完毕
yield return www;
//加载数据并赋值给AssetBundle
AssetBundle bundle = www.assetBundle;
//LoadAssetAsync异步加载包中资源传递给request,request中存放的是名字为Cube.prefab的数据
AssetBundleRequest request = bundle.LoadAssetAsync("Cube.prefab", typeof(GameObject));
go = Instantiate(request.asset as GameObject, new Vector3(0f, 0f, 0f), Quaternion.identity) as GameObject;
yield return request;
//释放资源
www.Dispose();
}
}

4.3 从本地下载资源

【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity模型服务器加载_13

源代码:

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

public class LoadBundles : MonoBehaviour
{
GameObject go;
void Start()
{
StartCoroutine(Load());
}

IEnumerator Load()
{
//从本地文件中加载
WWW www = new WWW("file://D:/Frank/UnityProject/Demo-1/Assets/ABs/cube01.unity3d");
//等待文件下载完毕
yield return www;
//加载数据并赋值给AssetBundle
AssetBundle bundle = www.assetBundle;
//LoadAssetAsync异步加载包中资源传递给request,request中存放的是名字为Cube.prefab的数据
AssetBundleRequest request = bundle.LoadAssetAsync("Cube.prefab", typeof(GameObject));
go = Instantiate(request.asset as GameObject, new Vector3(0f, 0f, 0f), Quaternion.identity) as GameObject;
yield return request;
www.Dispose();
}
}

五、测试例子

##步骤:

  1. 新建脚本PackBundles.cs放在Editor文件中
    编辑脚本
    【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity服务器下载模型_14
  2. 新建脚本LoadBundles.cs随意放那个文件夹都行
    编辑脚本:
    【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity服务器下载模型_15
  3. 打包资源
    【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_AssetBundle_04
    【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_Unity服务器下载模型_09
  4. 把加载脚本LoadBundles.cs挂载在场景中的任意物体上
    【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_AssetBundle_18
  5. 成功加载生成
    【Unity3D日常开发】5.0版本之后的AssetBundle资源的打包和解析加载_AssetBundle_19


PS:途中的Cube是我设置好的Cube预制体,加上了一个材质


OK,文章结束


PS:如果想要加载网上资源,就把打包好的包放到服务器上,然后通过地址,WWW类下载下来,解析加载就行了。