【Unity3D】5.0版本之後的AssetBundle資源的打包和解析載入
一、前言
這幾天在研究AssetBundle資源打包盒解析載入,也踩過很多坑,參考過很多人的文章
發現很多人關於AssetBundle的文章不是API過時了不能用,就是有點亂
也不是有點亂,就是摸不著頭腦,讓人不能快速的get到這個東西如何使用
所以我特意在踩過坑之後把我這個學到的經驗分享給大家。
PS: 一把辛酸淚
二、參考文章
PS:從參考的文章就知道踩了多少坑了
三、AssetBundle打包方式
3.1 API
- BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget
- BuildAssetBundles(string outputPath,AssetBundleBuild[] builds,BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform);
3.2 引數說明
outputPath:包Bundle後儲存的目錄,如:Assets/AssetBundles,這個資料夾不會自動建立,如果它不存在的話,函式將會失敗
BuildAssetBundleOptions:Bundle打包方式,none沒有任何特殊選項,UncompressedAssetBundle在構建Bundle時不要壓縮資料等等
BuildTarget
AssetBundleBuild[]:這個類與BuildAssetBundles一起使用。指定一個Bundle包的名稱assetBundleName和它將包含的資源(如多張圖片、音訊等)的名稱。
被傳遞給函式的AssetBundleBuild[]元素陣列被稱為“構建對映”,並作為指定編輯器包內容的替代方法。
AssetBundleBuild[]變數:
addressableNames:返回所有的addressableName陣列
assetBundleName:AssetBundle的名字
assetBundleVariant:AssetBundle的副檔名如.unity
AssetBundle
3.3 例子
- 新建一個指令碼PackBundles.cs,放到Editor資料夾中
- 編輯程式碼
原始碼:
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的圖片
點選PackBundles
這就將Texture中的123.jpg打包到123.unity3d中了
第二種,全部打包AllPackBundles
需要先在編輯器設定好引數
然後打包
這就將名字為Cube的預製體打包進入cube.unity3d
四、AssetBundle解析載入
4.1 API講解
4.1.1 載入AssetBundle的API
//載入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 從網上下載資源
原始碼:
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 從本地下載資源
原始碼:
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();
}
}
五、測試例子
##步驟:
- 新建指令碼PackBundles.cs放在Editor檔案中
編輯指令碼
- 新建指令碼LoadBundles.cs隨意放那個資料夾都行
編輯指令碼:
- 打包資源
- 把載入指令碼LoadBundles.cs掛載在場景中的任意物體上
- 成功載入生成
PS:途中的Cube是我設定好的Cube預製體,加上了一個材質
OK,文章結束
PS:如果想要載入網上資源,就把打包好的包放到伺服器上,然後通過地址,WWW類下載下來,解析載入就行了。