原文地址:http://www.cnblogs.com/88999660/archive/2013/04/10/3011912.html
首先要鄙視下unity3d的文檔編寫人員極度不負責任,到發帖為止依然沒有更新正確的示例代碼。
// C# Example // Builds an asset bundle from the selected objects in the project view. // Once compiled go to "Menu" -> "Assets" and select one of the choices // to build the Asset Bundle using UnityEngine; using UnityEditor; using System.IO; public class ExportAssetBundles { [MenuItem("Assets/Build AssetBundle Binary file From Selection - Track dependencies ")] static void ExportResource () { // Bring up save panel string path = EditorUtility.SaveFilePanel ("Save Resource", "", "New Resource", "unity3d"); if (path.Length != 0) { // Build the resource file from the active selection. Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets); BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets); Selection.objects = selection; FileStream fs = new FileStream(path,FileMode.Open,FileAccess.ReadWrite); byte[] buff = new byte[fs.Length+1]; fs.Read(buff,0,(int)fs.Length); buff[buff.Length-1] = 0; fs.Close(); File.Delete(path); string BinPath = path.Substring(0,path.LastIndexOf('.'))+".bytes"; // FileStream cfs = new FileStream(BinPath,FileMode.Create); cfs.Write(buff,0,buff.Length); buff =null; cfs.Close(); // string AssetsPath = BinPath.Substring(BinPath.IndexOf("Assets")); // Object ta = AssetDatabase.LoadAssetAtPath(AssetsPath,typeof(Object)); // BuildPipeline.BuildAssetBundle(ta, null, path); } } [MenuItem("Assets/Build AssetBundle From Selection - No dependency tracking")] static void ExportResourceNoTrack () { // Bring up save panel string path = EditorUtility.SaveFilePanel ("Save Resource", "", "New Resource", "unity3d"); if (path.Length != 0) { // Build the resource file from the active selection. BuildPipeline.BuildAssetBundle(Selection.activeObject, Selection.objects, path); } }
把打包的文件轉換成了binary文件並多加了一個字節加密。
當bytes文件生成好后再選中它,使用"Assets/Build AssetBundle From Selection - No dependency tracking"再次打包。
using UnityEngine; using System.Collections; using System; public class WWWLoadTest : MonoBehaviour { public string BundleURL; public string AssetName; IEnumerator Start() { WWW www =WWW.LoadFromCacheOrDownload(BundleURL,2); yield return www; TextAsset txt = www.assetBundle.Load("characters",typeof(TextAsset)) as TextAsset; byte[] data = txt.bytes; byte[] decryptedData = Decryption(data); Debug.LogError("decryptedData length:"+decryptedData.Length); StartCoroutine(LoadBundle(decryptedData)); } IEnumerator LoadBundle(byte[] decryptedData){ AssetBundleCreateRequest acr = AssetBundle.CreateFromMemory(decryptedData); yield return acr; AssetBundle bundle = acr.assetBundle; Instantiate(bundle.Load(AssetName)); } byte[] Decryption(byte[] data){ byte[] tmp = new byte[data.Length-1]; for(int i=0;i<data.Length-1;i++){ tmp[i] = data[i]; } return tmp; } }
WWW.LoadFromCacheOrDownload的作用就是下載並緩存資源,要注意后面的版本號參數,如果替換了資源卻沒有更新版本號,客戶端依然會加載緩存中的文件。
www.assetBundle.Load("characters",typeof(TextAsset)) as TextAsset //characters是加密文件的名字
AssetBundleCreateRequest acr = AssetBundle.CreateFromMemory(decryptedData);
這句是官網最坑爹的,AssetBundle.CreateFromMemory明 明返回的是AssetBundleCreateRequest官網卻寫得是AssetBundle,而且 AssetBundleCreateRequest是一個異步加載,必須用協程的方式加載官網也沒有提到。跟多兄弟就倒在了這里
完。
原理這里要說明下,是這樣子的,先把資源變成。unity3d格式,然后轉成。bytes格式,再轉成。unity3d格式,
加載的時候加載。unity3d格式,解析,然后變資源
我經過測試給出我的代碼:
using UnityEngine; using System.Collections; using UnityEditor; using System.IO; public class assetPack : Editor { //打包單個 [MenuItem("Custom Editor/Create AssetBunldes Main")] static void CreateAssetBunldesMain () { //獲取在Project視圖中選擇的所有游戲對象 Object[] SelectedAsset = Selection.GetFiltered (typeof(Object), SelectionMode.DeepAssets); //遍歷所有的游戲對象 foreach (Object obj in SelectedAsset) { //本地測試:建議最后將Assetbundle放在StreamingAssets文件夾下,如果沒有就創建一個,因為移動平台下只能讀取這個路徑 //StreamingAssets是只讀路徑,不能寫入 //服務器下載:就不需要放在這里,服務器上客戶端用www類進行下載。 string targetPath = Application.dataPath + "/StreamingAssets/" + obj.name + ".assetbundle"; if (BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies)) { Debug.Log(obj.name +"資源打包成功"); } else { Debug.Log(obj.name +"資源打包失敗"); } } //刷新編輯器 AssetDatabase.Refresh (); } [MenuItem("Custom Editor/Create AssetBunldes ALL")] static void CreateAssetBunldesALL () { Caching.CleanCache (); string Path = Application.dataPath + "/StreamingAssets/ALL.assetbundle"; Object[] SelectedAsset = Selection.GetFiltered (typeof(Object), SelectionMode.DeepAssets); foreach (Object obj in SelectedAsset) { Debug.Log ("Create AssetBunldes name :" + obj); } //這里注意第二個參數就行 if (BuildPipeline.BuildAssetBundle (null, SelectedAsset, Path, BuildAssetBundleOptions.CollectDependencies)) { AssetDatabase.Refresh (); } else { } } [MenuItem("Custom Editor/Create Scene")] static void CreateSceneALL () { //清空一下緩存 Caching.CleanCache(); string Path = Application.dataPath + "/eScene.unity3d"; string[] levels = { "Assets/myScene.unity" }; //打包場景 BuildPipeline.BuildPlayer( levels, Path,BuildTarget.StandaloneWindows, BuildOptions.BuildAdditionalStreamedScenes); AssetDatabase.Refresh (); } [MenuItem("Custom Editor/Save Scene")] static void ExportScene() { // 打開保存面板,獲得用戶選擇的路徑 string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "unity3d"); if (path.Length != 0) { // 選擇的要保存的對象 Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets); string[] scenes = { "Assets/myScene.unity" }; //打包 BuildPipeline.BuildPlayer(scenes, path, BuildTarget.StandaloneWindows, BuildOptions.BuildAdditionalStreamedScenes); } AssetDatabase.Refresh(); } [MenuItem("Custom Editor/Save Scene2")] static void ExportResource() { // Bring up save panel string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "unity3d"); if (path.Length != 0) { // Build the resource file from the active selection. Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets); BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets); Selection.objects = selection; } } [MenuItem("Custom Editor/Build AssetBundle From Selection - Track dependencies")] static void ExportResource2() { // Bring up save panel string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "unity3d"); if (path.Length != 0) { // Build the resource file from the active selection. Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets); BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets); Selection.objects = selection; } } [MenuItem("Custom Editor/Build AssetBundle Complited to bytes")] static void ExportResource5() { // Bring up save panel string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "unity3d"); if (path.Length != 0) { // Build the resource file from the active selection. Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets); BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets, BuildTarget.StandaloneWindows); Selection.objects = selection; FileStream fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite); byte[] buff = new byte[fs.Length + 1]; fs.Read(buff, 0, (int)fs.Length); buff[buff.Length - 1] = 0; Debug.Log("filelength:"+ buff.Length); fs.Close(); File.Delete(path); string BinPath = path.Substring(0, path.LastIndexOf('.')) + ".bytes"; FileStream cfs = new FileStream(BinPath,FileMode.Create); cfs.Write(buff, 0, buff.Length); Debug.Log("filelength:" + buff.Length); buff = null; cfs.Close(); } } [MenuItem("Custom Editor/Build AssetBundle From Selection Twice")] static void ExportResourceNoTrack() { // Bring up save panel string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "unity3d"); if (path.Length != 0) { // Build the resource file from the active selection. BuildPipeline.BuildAssetBundle(Selection.activeObject, Selection.objects, path); } } }
加載部分
using UnityEngine; using System.Collections; public class loadnew : MonoBehaviour { public string filename; private string BundleURL; private string AssetName; IEnumerator Start() { BundleURL = "file://" + Application.dataPath +"/"+ filename+".unity3d"; Debug.Log("path:"+ BundleURL); WWW m_Download = new WWW(BundleURL); yield return m_Download; if (m_Download.error != null) { // Debug.LogError(m_Download.error); Debug.Log("Warning errow: " + "NewScene"); yield break; } TextAsset txt = m_Download.assetBundle.Load(filename, typeof(TextAsset)) as TextAsset; byte[] data = txt.bytes; byte[] decryptedData = Decryption(data); Debug.Log("decryptedData length:" + decryptedData.Length); StartCoroutine(LoadBundle(decryptedData)); } IEnumerator LoadBundle(byte[] decryptedData) { AssetBundleCreateRequest acr = AssetBundle.CreateFromMemory(decryptedData); yield return acr; AssetBundle bundle = acr.assetBundle; Instantiate(bundle.mainAsset); } byte[] Decryption(byte[] data) { byte[] tmp = new byte[data.Length - 1]; for (int i = 0; i < data.Length - 1; i++) { tmp[i] = data[i]; } return tmp; } void update() { } }
