一、AssetBundle定義和作用(後面簡稱AB)
官方介紹:https://docs.unity3d.com/Manual/AssetBundlesIntro.html
- AssetBundle是一個壓縮包包含模型、貼圖、預製體、聲音、甚至整個場景,可以在遊戲運行時被加載(熱更);
- AssetBundle自身保存着互相的依賴關係(模型包依賴貼圖包);
- 壓縮包可以使用LZMA和LZ4壓縮算法,減少包大小,更快的進行網絡傳輸;
- 把一些可以下載內容放在AssetBundle裏面,可以減少安裝包的大小;
二、什麼是AssetBundle
可歸爲兩點
它是一個存在於硬盤上的文件。可以稱之爲壓縮包。這個壓縮包可以認爲是一個文件夾,裏面包含了多個文件。這些文件可以分爲兩類:serialized file 和 resource files。(序列化文件和源文件)
serialized file:資源(在遊戲場景中才能被識別如:模型、預製體)被打碎放在一個對象中,最後統一被寫進一個單獨的文件(只有一個)
resource files:某些二進制資源(可直接在電腦上讀取如:圖片、聲音)被單獨保存,方便快速加載它是一個AssetBundle對象,我們可以通過代碼從一個特定的壓縮包加載出來的對象。這個對象包含了所有我們當初添加到這個壓縮包裏面的內容,我們可以通過這個對象加載出來使用。
三、AssetBundle使用流程(簡稱AB)
1. 指定資源的AssetBundle屬性
1. 這兒 (xxx/Cube) == (xxx/cube) 是不區分大小寫的
…
2. 構建AssetBundle包
- 根目錄Assets下創建一個Editor文件夾,再創建一個.cs文件使用下方代碼
- 點擊菜單欄 Assets -> Build AssetBundles,打包成功後在目錄【Assets/AssetBundles】中就能看到打包好的資源
public class CreateAssetBundles
{
//相當於是拓展編譯器,在Assets下創建一個Build AssetBundles菜單
[MenuItem("Assets/Build AssetBundles")]
static void BuildAllAssetBundles()
{
//string assetBundleDirectory = Path.Combine(Application.streamingAssetsPath, "AssetBundles");//"Assets/AssetBundles";
string assetBundleDirectory = "Assets/AssetBundles";
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}
//打包的輸出路徑、打包方式、平臺
/* BuildAssetBundleOptions
* BuildAssetBundleOptions.None:使用LZMA算法壓縮,壓縮的包更小,但是加載時間更長。使用之前需要整體解壓。
* 一旦被解壓,這個包會使用LZ4重新壓縮。使用資源的時候不需要整體解壓。在下載的時候可以使用LZMA算法,
* 一旦它被下載了之後,它會使用LZ4算法保存到本地上。
* BuildAssetBundleOptions.UncompressedAssetBundle:不壓縮,包大,加載快
* BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4壓縮,壓縮率沒有LZMA高,但是我們可以加載指定資源而不用解壓全部。
*/
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
}
}
3. 上傳AB包到服務器
一般都要在本地調試,等遊戲發佈時纔會上次到服務器
4. 加載AB包和包裏面的資源(本地、服務端)
這裏有個知識點協程:http://www.cnblogs.com/neverdie/p/3792766.html#_nav_5
public class LoadFromFileExample : MonoBehaviour
{
//LoadFromFile本地加載 LoadFromMemory加載字節流
void Start() {
//如果材質是獨立的一個包,就需要加載材質
AssetBundle share = AssetBundle.LoadFromFile("Assets/AssetBundles/material.test");
//加載模型
AssetBundle ab = AssetBundle.LoadFromFile("Assets/AssetBundles/scene/sphere.test");
//從內存加載
//AssetBundle ab = AssetBundle.LoadFromMemory(File.ReadAllBytes(path));
if (ab == null)
{
Debug.Log("Failed to load AssetBundle!");
return;
}
var prefab = ab.LoadAsset<GameObject>("Sphere");
GameObject.Instantiate(prefab);
}
//UnityWebRequest 服務端或者本地加載
IEnumerator Start()
{
//服務器地址
string uri = @"http://localhost//AssetBundles/scene/sphere.test";
//本地地址
//string uri = @"file://D:/Unity3d/APlan_Siki/09_AssetBundleProject/Assets/AssetBundles/scene/sphere.test";
UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();//開始下載到緩存
AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
var prefab = ab.LoadAsset<GameObject>("Sphere");
GameObject.Instantiate(prefab);
}
}
四、AssetBundle分組策略 (僅供參考)
- 邏輯實體分組
a. 一個UI界面或者所有UI界面一個包(這個界面裏面的貼圖和佈局信息一個包)
b. 一個角色或者所有角色一個包(這個角色裏面的模型和動畫一個包)
c. 所有的場景所共享的部分一個包(包括貼圖和模型) - 按照類型分組
所有聲音資源打成一個包,所有shader打成一個包,所有模型打成一個包,所有材質打成一個包 按照使用分組
把在某一時間內使用的所有資源打成一個包。可以按照關卡分,一個關卡所需要的所有資源包括角色、貼圖、聲音等打成一個包。也可以按照場景分,一個場景所需要的資源一個包把經常更新的資源放在一個單獨的包裏面,跟不經常更新的包分離
- 把需要同時加載的資源放在一個包裏面
- 依賴打包:可以把其他包共享的資源放在一個單獨的包裏面(避免同一份資源跟多個依賴的perfab打包在一起)
- 把一些需要同時加載的小資源打包成一個包
- 如果對於一個同一個資源有兩個版本,可以考慮通過後綴來區分 v1 v2 v3 unity3dv1 unity3dv2
五、通過Manifest文件得到某個包所有的依賴
//AssetBundles的路徑 獲取AssetBundles
AssetBundle assetBundle = AssetBundle.LoadFromFile("Assets/AssetBundles/AssetBundles");
//固定不變 得到AssetBundles.manifest
AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
//哪個的包? 得到這個包的所有依賴
string[] dependencies = manifest.GetAllDependencies("scene/sphere.test");
foreach (string dependency in dependencies)
{
AssetBundle.LoadFromFile(Path.Combine("Assets/AssetBundles", dependency));//加載這個包的依賴
}
六、AssetBundle的卸載
- 卸載有兩個方面: 1.減少內存使用 2.有可能導致丟失
- 所以什麼時候去卸載資源: 1.關卡切換、場景切換 2.資源沒被用的時候 調用
- 個別資源怎麼卸載: 1.通過 Resources.UnloadUnusedAssets. 2.場景切換的時候
- AssetBundle.Unload(true)卸載所有資源,即使有資源被使用着
- AssetBundle.Unload(false)卸載所有沒用被使用的資源
七、關於文件校驗 CRC MD5 SHA1
- 相同點:
- 都是通過對數據進行計算,來生成一個校驗值,該校驗值用來校驗數據的完整性。
- 不同點:
- 算法不同。CRC採用多項式除法,MD5和SHA1使用的是替換、輪轉等方法;
- 校驗值的長度不同。CRC校驗位的長度跟其多項式有關係,一般爲16位或32位;MD5是16個字節(128位);SHA1是20個字節(160位);
- 校驗值的稱呼不同。CRC一般叫做CRC值;MD5和SHA1一般叫做哈希值(Hash)或散列值;
- 安全性不同。這裏的安全性是指檢錯的能力(數據有誤,但生成的校驗值確和原來一樣,則檢錯能力低),即數據的錯誤能通過校驗位檢測出來。CRC的安全性跟多項式有很大關係,相對於MD5和SHA1要弱很多;MD5的安全性很高,不過大概在04年的時候被山東大學的王小云破解了;SHA1的安全性最高。
- 效率不同,CRC的計算效率很高;MD5和SHA1比較慢。
- 用途不同。CRC一般用作通信數據的校驗;MD5和SHA1用於安全(Security)領域,比如文件校驗、數字簽名等。
八、AssetBundles瀏覽工具
官網介紹:https://docs.unity3d.com/Manual/AssetBundles-Browser.html
工具Git地址:https://github.com/Unity-Technologies/AssetBundles-Browser
將Editor導入我們的工程,然後點擊 Window–>AssetBundle Browser 就會彈出工具界面,可以對打包的資源一目瞭然。