• Unity5 AssetBundle资源管理架构设计


    http://blog.csdn.net/qq_19399235/article/details/51702964

    1:Unity5 资源管理架构设计(2017.4.22版本)

    2:Android 热更新(不考虑IOS)根据C#反射实现的代码全更新方案(网上一大坨,我重新整理一下)。



    一:Unity资源管理架构设计

    注意:我配置的Bundle资源文件都放在Assets/ResourceABs文件夹下,并且此文件夹下每个文件夹都对应一个Bundle文件,最终这些文件都打包到StreamingAssets流文件夹下。

    1:设计一个资源信息管理类,能够反映Assets/ResourceABs文件夹下的全部的资源信息。
    生成工具放在Editor文件下, 代码如下:
    [csharp] view plain copy
    1. using UnityEngine;  
    2. using System.Collections;  
    3. using System.IO;  
    4. using UnityEditor;  
    5. using xk_System.AssetPackage;  
    6.   
    7. public class ExportAssetInfoEditor : MonoBehaviour  
    8. {  
    9.     static string extention = AssetBundlePath.ABExtention;  
    10.     static string BuildAssetPath = "Assets/ResourceABs";  
    11.     static string CsOutPath = "Assets/Scripts/auto";  
    12.   
    13.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~创建AB文件所有的信息~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    14.     [MenuItem("UnityEditor/GenerationPackage/Generation AssetInfo Cs File")]  
    15.     public static void GenericAssetCSInfo()  
    16.     {  
    17.         Debug.Log("Start Generation AssetInfo Cs Info");  
    18.         CreateABCSFile();  
    19.         Debug.Log("Finish Generation AssetInfo Cs Info");  
    20.     }  
    21.   
    22.     private static void CreateABCSFile()  
    23.     {  
    24.         string m = "";  
    25.         m += "namespace xk_System.AssetPackage { ";  
    26.         DirectoryInfo mDir = new DirectoryInfo(BuildAssetPath);  
    27.         m += " public class " + mDir.Name + "Folder : Singleton<" + mDir.Name + "Folder> { ";  
    28.         string s = "";  
    29.         foreach (var v in mDir.GetDirectories())  
    30.         {  
    31.             FileInfo[] mFileInfos1 = v.GetFiles();  
    32.             int mFilesLength1 = 0;  
    33.             foreach (var v1 in mFileInfos1)  
    34.             {  
    35.                 if (v1.Extension != ".meta")  
    36.                 {  
    37.                     mFilesLength1++;  
    38.                     break;  
    39.                 }  
    40.             }  
    41.             if (mFilesLength1 > 0 || v.GetDirectories().Length > 0)  
    42.             {  
    43.                 string fieldName = v.Name + "Folder";  
    44.                 m += "  public " + fieldName + " " + v.Name + "=new " + fieldName + "(); ";  
    45.                // s += CreateDirClass(v, v.Name.ToLower());  
    46.             }  
    47.         }  
    48.         foreach (var v in mDir.GetDirectories())  
    49.         {  
    50.             m += CreateDirClass(v, v.Name.ToLower());  
    51.         }  
    52.         m += " } ";  
    53.        // m += s;  
    54.         m += "} ";  
    55.         string fileName = CsOutPath + "/" + mDir.Name + ".cs";  
    56.         StreamWriter mSw = new StreamWriter(fileName, false);  
    57.         mSw.Write(m);  
    58.         mSw.Close();  
    59.     }  
    60.   
    61.     private static string CreateDirClass(DirectoryInfo mDir, string bundleName)  
    62.     {  
    63.         string tStr = GetTStr(mDir);  
    64.         string m = "";  
    65.         string s = "";  
    66.         FileInfo[] mFileInfos = mDir.GetFiles();  
    67.         int mFilesLength = 0;  
    68.         foreach (var v in mFileInfos)  
    69.         {  
    70.             if (v.Extension != ".meta")  
    71.             {  
    72.                 mFilesLength++;  
    73.                 break;  
    74.             }  
    75.         }  
    76.         if (mFilesLength > 0)  
    77.         {  
    78.             string bundleName1 = bundleName+ extention;  
    79.             m = tStr+"public class " + mDir.Name + "Folder "+tStr+"{ ";  
    80.             foreach (var v in mFileInfos)  
    81.             {  
    82.                 if (v.Extension != ".meta")  
    83.                 {  
    84.                     string assetPath = GetAssetPath(v.FullName);  
    85.                     string fileName = v.Name.Substring(0, v.Name.LastIndexOf(v.Extension));  
    86.                     m += tStr+"  public AssetInfo m" + fileName + "=new AssetInfo(""+assetPath+"","" + bundleName1 + "","" + v.Name + ""); ";  
    87.                 }  
    88.             }  
    89.             m += tStr+"} ";  
    90.         }  
    91.         else  
    92.         {  
    93.             if (mDir.GetDirectories().Length > 0)  
    94.             {  
    95.   
    96.                 m = tStr+"public class " + mDir.Name + "Folder "+tStr+"{ ";  
    97.                 foreach (var v in mDir.GetDirectories())  
    98.                 {  
    99.                     FileInfo[] mFileInfos1 = v.GetFiles();  
    100.                     int mFilesLength1 = 0;  
    101.                     foreach (var v1 in mFileInfos1)  
    102.                     {  
    103.                         if (v1.Extension != ".meta")  
    104.                         {  
    105.                             mFilesLength1++;  
    106.                             break;  
    107.                         }  
    108.                     }  
    109.                     if (mFilesLength1 > 0 || v.GetDirectories().Length > 0)  
    110.                     {  
    111.                         string fieldName = v.Name + "Folder";  
    112.                         m += tStr+"  public " + fieldName + " " + v.Name + "=new " + fieldName + "(); ";  
    113.                     }  
    114.                 }  
    115.                 foreach (var v in mDir.GetDirectories())  
    116.                 {  
    117.                     m += CreateDirClass(v, bundleName + "_" + v.Name.ToLower());  
    118.                 }  
    119.                 m += tStr+"} ";  
    120.                // m += s;  
    121.             }  
    122.         }  
    123.         return m;  
    124.     }  
    125.     public static string GetTStr(DirectoryInfo mDir)  
    126.     {  
    127.         int coutT = 0;  
    128.         int index = mDir.FullName.IndexOf(@"ResourceABs");  
    129.         if (index >= 0)  
    130.         {  
    131.             for(int j=0;j<mDir.FullName.Length;j++)  
    132.             {  
    133.                 if (j > index)  
    134.                 {  
    135.                     var v = mDir.FullName[j];  
    136.                     if (v.Equals('\'))  
    137.                     {  
    138.                         coutT++;  
    139.                     }  
    140.                 }  
    141.             }  
    142.         }  
    143.         coutT++;  
    144.         string tStr = "";  
    145.         int i = 0;  
    146.         while(i<coutT)  
    147.         {  
    148.             tStr += " ";  
    149.             i++;  
    150.         }  
    151.         return tStr;  
    152.     }  
    153.   
    154.     public static string GetAssetPath(string filePath)  
    155.     {  
    156.         string assetPath = "";  
    157.         int index = filePath.IndexOf(@"Assets");  
    158.         if (index >= 0)  
    159.         {  
    160.             assetPath = filePath.Remove(0, index);  
    161.             assetPath = assetPath.Replace(@"","/");  
    162.         }  
    163.         return assetPath;  
    164.     }  
    165.   
    166. }  
    到这里,这个资源基本信息管理类就处理好了。
    2:我们就正式开始写资源管理架构类了
    我们首先写一个AssetBundleManager类,这个类的目的专门用来更新完毕后,充当资源加载管理器。代码如下
    [csharp] view plain copy
    1. using UnityEngine;  
    2. using System.Collections;  
    3. using xk_System.Debug;  
    4. using System.Collections.Generic;  
    5. using System.Xml;  
    6.   
    7. namespace xk_System.AssetPackage  
    8. {  
    9.     /// <summary>  
    10.     /// 此类的目的就是加载本地的Bundle进行资源读取操作的  
    11.     /// </summary>  
    12.     public class AssetBundleManager : SingleTonMonoBehaviour<AssetBundleManager>  
    13.     {  
    14.         private ResourcesABManager mResourcesABManager = new ResourcesABManager();  
    15.         private Dictionary<string, AssetBundle> mBundleDic = new Dictionary<string, AssetBundle>();  
    16.         private Dictionary<string, Dictionary<string, UnityEngine.Object>> mAssetDic = new Dictionary<string, Dictionary<string, UnityEngine.Object>>();  
    17.         private List<string> mBundleLockList = new List<string>();  
    18.   
    19.         /// <summary>  
    20.         /// 加载Assetbundle方案1:初始化时,全部加载  
    21.         /// </summary>  
    22.         /// <returns></returns>  
    23.         public IEnumerator InitLoadAllBundleFromLocal()  
    24.         {  
    25.             yield return mResourcesABManager.InitLoadMainifestFile();  
    26.             List<AssetBundleInfo> bundleList = mResourcesABManager.mNeedLoadBundleList;  
    27.             List<AssetBundleInfo>.Enumerator mIter = bundleList.GetEnumerator();  
    28.             while (mIter.MoveNext())  
    29.             {  
    30.                 yield return AsyncLoadFromLoaclSingleBundle(mIter.Current);  
    31.             }  
    32.         }  
    33.         public IEnumerator InitAssetBundleManager()  
    34.         {  
    35.             yield return mResourcesABManager.InitLoadMainifestFile();  
    36.         }  
    37.   
    38.         private IEnumerator CheckBundleDependentBundle(AssetBundleInfo mBundle)  
    39.         {  
    40.             if (mBundle != null)  
    41.             {  
    42.                 string[] mdependentBundles = mBundle.mDependentBundleList;  
    43.                 foreach (string s in mdependentBundles)  
    44.                 {  
    45.                     AssetBundleInfo mBundleInfo = mResourcesABManager.GetBundleInfo(s);  
    46.                     if (mBundleInfo != null)  
    47.                     {  
    48.                         AssetBundle mAB = null;  
    49.                         if (!mBundleDic.TryGetValue(mBundleInfo.bundleName, out mAB))  
    50.                         {  
    51.                             yield return AsyncLoadFromLoaclSingleBundle(mBundleInfo);  
    52.                         }  
    53.                         else  
    54.                         {  
    55.                             if (mAB == null)  
    56.                             {  
    57.                                 yield return AsyncLoadFromLoaclSingleBundle(mBundleInfo);  
    58.                             }  
    59.                         }  
    60.                     }  
    61.                 }  
    62.             }  
    63.         }  
    64.         /// <summary>  
    65.         /// 从本地外部存储位置加载单个Bundle资源,全部加载  
    66.         /// </summary>  
    67.         /// <param name="BaseBundleInfo"></param>  
    68.         /// <returns></returns>  
    69.         private IEnumerator AsyncLoadFromLoaclSingleBundle1(AssetBundleInfo BaseBundleInfo)  
    70.         {  
    71.             if(mBundleLockList.Contains(BaseBundleInfo.bundleName))  
    72.             {  
    73.                 while(mBundleLockList.Contains(BaseBundleInfo.bundleName))  
    74.                 {  
    75.                     yield return null;  
    76.                 }  
    77.                 yield break;  
    78.             }       
    79.             mBundleLockList.Add(BaseBundleInfo.bundleName);  
    80.             yield return CheckBundleDependentBundle(BaseBundleInfo);  
    81.             string path = AssetBundlePath.Instance.ExternalStorePathUrl;  
    82.             string url = path + "/" + BaseBundleInfo.bundleName;  
    83.             WWW www = new WWW(url);  
    84.             yield return www;  
    85.             if (www.isDone)  
    86.             {  
    87.                 if (!string.IsNullOrEmpty(www.error))  
    88.                 {  
    89.                     DebugSystem.LogError("www Load Error:" + www.error);  
    90.                     www.Dispose();  
    91.                     mBundleLockList.Remove(BaseBundleInfo.bundleName);  
    92.                     yield break;  
    93.                 }  
    94.             }  
    95.             AssetBundle asset = www.assetBundle;  
    96.             SaveBundleToDic(BaseBundleInfo.bundleName, asset);  
    97.             mBundleLockList.Remove(BaseBundleInfo.bundleName);  
    98.             www.Dispose();  
    99.         }  
    100.   
    101.         /// <summary>  
    102.         /// 从本地外部存储位置加载单个Bundle资源,全部加载  
    103.         /// </summary>  
    104.         /// <param name="BaseBundleInfo"></param>  
    105.         /// <returns></returns>  
    106.         private IEnumerator AsyncLoadFromLoaclSingleBundle(AssetBundleInfo BaseBundleInfo)  
    107.         {  
    108.             if (mBundleLockList.Contains(BaseBundleInfo.bundleName))  
    109.             {  
    110.                 while (mBundleLockList.Contains(BaseBundleInfo.bundleName))  
    111.                 {  
    112.                     yield return null;  
    113.                 }  
    114.                 yield break;  
    115.             }  
    116.             mBundleLockList.Add(BaseBundleInfo.bundleName);  
    117.             yield return CheckBundleDependentBundle(BaseBundleInfo);  
    118.             string path = AssetBundlePath.Instance.ExternalStorePath+"/"+BaseBundleInfo.bundleName;  
    119.             AssetBundleCreateRequest www= AssetBundle.LoadFromFileAsync(path);  
    120.             www.allowSceneActivation = true;  
    121.             yield return www;  
    122.             AssetBundle asset = www.assetBundle;  
    123.             SaveBundleToDic(BaseBundleInfo.bundleName, asset);  
    124.             mBundleLockList.Remove(BaseBundleInfo.bundleName);  
    125.         }  
    126.         /// <summary>  
    127.         /// 异步从本地外部存储加载单个Asset文件,只加载Bundle中的单个资源  
    128.         /// </summary>  
    129.         /// <param name="bundle"></param>  
    130.         /// <returns></returns>  
    131.         private IEnumerator AsyncLoadFromLocalSingleAsset(AssetBundleInfo bundle, string assetName)  
    132.         {  
    133.             if (bundle != null)  
    134.             {  
    135.                 yield return AsyncLoadFromLoaclSingleBundle(bundle);  
    136.                 UnityEngine.Object Obj = mBundleDic[bundle.bundleName].LoadAsset(assetName);  
    137.                 if (Obj != null)  
    138.                 {  
    139.                     DebugSystem.Log("Async Load Asset Success:" + Obj.name);  
    140.                     SaveAssetToDic(bundle.bundleName, assetName, Obj);  
    141.                 }  
    142.             }  
    143.         }  
    144.         /// <summary>  
    145.         /// 同步从本地外部存储加载单个Bundle文件  
    146.         /// </summary>  
    147.         /// <param name="BaseBundleInfo"></param>  
    148.         /// <param name="assetName"></param>  
    149.         /// <returns></returns>  
    150.         private void SyncLoadFromLocalSingleBundle(string bundleName)  
    151.         {  
    152.             if (!JudegeOrExistBundle(bundleName))  
    153.             {  
    154.                 string path = AssetBundlePath.Instance.ExternalStorePath + "/" + bundleName;  
    155.                 AssetBundle asset = AssetBundle.LoadFromFile(path);  
    156.                 SaveBundleToDic(bundleName, asset);  
    157.             }else  
    158.             {  
    159.                 DebugSystem.LogError("Bundle 已存在:"+bundleName);  
    160.             }  
    161.         }  
    162.   
    163.         /// <summary>  
    164.         /// 同步从本地外部存储加载单个资源文件  
    165.         /// </summary>  
    166.         /// <param name="BaseBundleInfo"></param>  
    167.         /// <param name="assetName"></param>  
    168.         /// <returns></returns>  
    169.         public UnityEngine.Object SyncLoadFromLocalSingleAsset(AssetInfo mAssetInfo)  
    170.         {  
    171.             if (!JudgeOrExistAsset(mAssetInfo.bundleName, mAssetInfo.assetName))  
    172.             {  
    173.                 string path = AssetBundlePath.Instance.ExternalStorePath+"/"+mAssetInfo.bundleName;  
    174.                 AssetBundle asset = AssetBundle.LoadFromFile(path);  
    175.                 SaveBundleToDic(mAssetInfo.bundleName,asset);  
    176.             }  
    177.             return GetAssetFromDic(mAssetInfo.bundleName,mAssetInfo.assetName);  
    178.         }  
    179.   
    180.   
    181.         private void SaveBundleToDic(string bundleName, AssetBundle bundle)  
    182.         {  
    183.             if (bundle == null)  
    184.             {  
    185.                 DebugSystem.LogError("未保存的Bundle为空:"+bundleName);  
    186.                 return;  
    187.             }  
    188.             if (!mBundleDic.ContainsKey(bundleName))  
    189.             {  
    190.                 mBundleDic[bundleName] = bundle;  
    191.             }else  
    192.             {  
    193.                 DebugSystem.LogError("Bundle资源 重复:"+bundleName);  
    194.             }  
    195.         }  
    196.   
    197.         private void SaveAssetToDic(string bundleName, string assetName, UnityEngine.Object asset)  
    198.         {  
    199.             if (asset == null)  
    200.             {  
    201.                 DebugSystem.LogError("未保存的资源为空:"+assetName);  
    202.                 return;  
    203.             }  
    204.             if(asset is GameObject)  
    205.             {  
    206.                 GameObject obj = asset as GameObject;  
    207.                 obj.SetActive(false);  
    208.             }  
    209.             if (!mAssetDic.ContainsKey(bundleName))  
    210.             {  
    211.                 Dictionary<string, UnityEngine.Object> mDic = new Dictionary<string, UnityEngine.Object>();  
    212.                 mAssetDic.Add(bundleName, mDic);  
    213.             }  
    214.             mAssetDic[bundleName][assetName] = asset;  
    215.         }  
    216.   
    217.         private bool JudgeOrBundelIsLoading(string bundleName)  
    218.         {  
    219.             if (mBundleLockList.Contains(bundleName))  
    220.             {  
    221.                 return true;  
    222.             }else  
    223.             {  
    224.                 return false;  
    225.             }  
    226.         }  
    227.   
    228.         private bool JudegeOrExistBundle(string bundleName)  
    229.         {  
    230.             if (mBundleDic.ContainsKey(bundleName) && mBundleDic[bundleName] != null)  
    231.             {  
    232.                 return true;  
    233.             }  
    234.             else  
    235.             {  
    236.                 return false;  
    237.             }  
    238.         }  
    239.   
    240.         private bool JudgeOrExistAsset(string bundleName, string asstName)  
    241.         {  
    242.             if (JudegeOrExistBundle(bundleName))  
    243.             {  
    244.                 if (!mAssetDic.ContainsKey(bundleName) || mAssetDic[bundleName] == null || !mAssetDic[bundleName].ContainsKey(asstName) || mAssetDic[bundleName][asstName] == null)  
    245.                 {  
    246.                     UnityEngine.Object mm = mBundleDic[bundleName].LoadAsset(asstName);  
    247.                     if (mm != null)  
    248.                     {  
    249.                         SaveAssetToDic(bundleName, asstName, mm);  
    250.                         return true;  
    251.                     }  
    252.                     else  
    253.                     {  
    254.                         return false;  
    255.                     }  
    256.                 }  
    257.                 else  
    258.                 {  
    259.                     return true;  
    260.                 }  
    261.             }  
    262.             else  
    263.             {  
    264.                 return false;  
    265.             }  
    266.         }  
    267.   
    268.         private UnityEngine.Object GetAssetFromDic(string bundleName, string asstName)  
    269.         {  
    270.             if (JudgeOrExistAsset(bundleName, asstName))  
    271.             {  
    272.                 UnityEngine.Object mAsset1 = mAssetDic[bundleName][asstName];  
    273.                 if (mAsset1 is GameObject)  
    274.                 {  
    275.                     GameObject obj = Instantiate(mAsset1) as GameObject;  
    276.                     return obj;  
    277.                 }  
    278.                 else  
    279.                 {  
    280.                     return mAsset1;  
    281.                 }  
    282.             }  
    283.             else  
    284.             {  
    285.                 DebugSystem.LogError("Asset is NUll:" + asstName);  
    286.             }  
    287.             return null;  
    288.         }  
    289. #if UNITY_EDITOR  
    290.         private Dictionary<string, UnityEngine.Object> mEditorAssetDic = new Dictionary<string, UnityEngine.Object>();  
    291.   
    292.         private UnityEngine.Object GetAssetFromEditorDic(string assetPath)  
    293.         {  
    294.             if (string.IsNullOrEmpty(assetPath))  
    295.             {  
    296.                 DebugSystem.LogError("Editor AssetPath is Empty");  
    297.                 return null;  
    298.             }  
    299.             UnityEngine.Object asset = null;  
    300.             if (!mEditorAssetDic.TryGetValue(assetPath, out asset))  
    301.             {  
    302.                 asset = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath);  
    303.                 if (asset != null)  
    304.                 {  
    305.                     if (asset is GameObject)  
    306.                     {  
    307.                         GameObject obj = asset as GameObject;  
    308.                         obj.SetActive(false);  
    309.                     }  
    310.                     mEditorAssetDic.Add(assetPath, asset);  
    311.                 }  
    312.                 else  
    313.                 {  
    314.                     DebugSystem.LogError("找不到资源:" + assetPath);  
    315.                 }  
    316.             }  
    317.             if (asset is GameObject)  
    318.             {  
    319.                 GameObject obj = Instantiate(asset) as GameObject;  
    320.                 return obj;  
    321.             }  
    322.             else  
    323.             {  
    324.                 return asset;  
    325.             }  
    326.         }  
    327. #endif  
    328.         public IEnumerator AsyncLoadBundle(string bundleName)  
    329.         {  
    330.             if (!JudegeOrExistBundle(bundleName))  
    331.             {  
    332.                 string path = AssetBundlePath.Instance.ExternalStorePath + "/" + bundleName;  
    333.                 AssetBundle asset = AssetBundle.LoadFromFile(path);  
    334.                 SaveBundleToDic(bundleName, asset);  
    335.                 yield return null;  
    336.             }            
    337.         }  
    338.         /// <summary>  
    339.         /// 这个东西用来在顶层使用  
    340.         /// </summary>  
    341.         /// <param name="type"></param>  
    342.         /// <param name="assetName"></param>  
    343.         /// <returns></returns>  
    344.         public UnityEngine.Object LoadAsset(AssetInfo mAssetInfo)  
    345.         {  
    346.             if (GameConfig.Instance.orUseAssetBundle)  
    347.             {  
    348.                 return GetAssetFromDic(mAssetInfo.bundleName, mAssetInfo.assetName);  
    349.             }  
    350.             else  
    351.             {  
    352.                return GetAssetFromEditorDic(mAssetInfo.assetPath);  
    353.             }  
    354.         }  
    355.   
    356.         /// <summary>  
    357.         /// 这个东西用来在专门的管理器中使用(底层封装一下),禁止在顶层使用  
    358.         /// </summary>  
    359.         /// <param name="type"></param>  
    360.         /// <param name="assetName"></param>  
    361.         /// <returns></returns>  
    362.         public IEnumerator AsyncLoadAsset(AssetInfo mAssetInfo)  
    363.         {  
    364.             if (GameConfig.Instance.orUseAssetBundle)  
    365.             {  
    366.                 string bundleName = mAssetInfo.bundleName;  
    367.                 string asstName = mAssetInfo.assetPath;  
    368.                 if (!JudgeOrExistAsset(bundleName, asstName))  
    369.                 {  
    370.                     yield return AsyncLoadFromLocalSingleAsset(mResourcesABManager.GetBundleInfo(bundleName), asstName);  
    371.                 }  
    372.             }  
    373.         }  
    374.     }  
    375.   
    376.     public class ResourcesABManager  
    377.     {  
    378.         public int VersionId = -1;  
    379.         public List<AssetBundleInfo> mNeedLoadBundleList = new List<AssetBundleInfo>();  
    380.         public AssetBundleInfo GetBundleInfo(string bundleName)  
    381.         {  
    382.             AssetBundleInfo mBundleInfo = mNeedLoadBundleList.Find((x) =>  
    383.             {  
    384.                 return x.bundleName == bundleName;  
    385.             });  
    386.             return mBundleInfo;  
    387.         }  
    388.   
    389.         public IEnumerator InitLoadMainifestFile()  
    390.         {  
    391.             if (mNeedLoadBundleList.Count == 0)  
    392.             {  
    393.                 string path = AssetBundlePath.Instance.ExternalStorePathUrl;  
    394.                 string url = path + "/" + AssetBundlePath.AssetDependentFileBundleName;  
    395.                 WWW www = new WWW(url);  
    396.                 yield return www;  
    397.                 if (www.isDone)  
    398.                 {  
    399.                     if (!string.IsNullOrEmpty(www.error))  
    400.                     {  
    401.                         DebugSystem.LogError("初始化 MainifestFile 失败:" + www.error);  
    402.                         www.Dispose();  
    403.                         yield break;  
    404.                     }  
    405.                 }  
    406.                 AssetBundle asset = www.assetBundle;  
    407.                 www.Dispose();  
    408.                 if (asset == null)  
    409.                 {  
    410.                     DebugSystem.LogError("MainifestFile Bundle is Null");  
    411.                     www.Dispose();  
    412.                     yield break;  
    413.                 }  
    414.   
    415.                 AssetBundleManifest mAllBundleMainifest = asset.LoadAsset<AssetBundleManifest>(AssetBundlePath.AssetDependentFileAssetName);  
    416.                 if (mAllBundleMainifest == null)  
    417.                 {  
    418.                     DebugSystem.LogError("Mainifest is Null");  
    419.                     www.Dispose();  
    420.                     yield break;  
    421.                 }  
    422.                 string[] mAssetNames = mAllBundleMainifest.GetAllAssetBundles();  
    423.                 if (mAssetNames != null)  
    424.                 {  
    425.                     foreach (var v in mAssetNames)  
    426.                     {  
    427.   
    428.                         string bundleName = v;  
    429.                         string[] bundleDependentList = mAllBundleMainifest.GetAllDependencies(v);  
    430.                         Hash128 mHash = mAllBundleMainifest.GetAssetBundleHash(v);  
    431.                         AssetBundleInfo mABInfo = new AssetBundleInfo(bundleName, mHash, bundleDependentList);  
    432.                         mNeedLoadBundleList.Add(mABInfo);  
    433.                     }  
    434.                 }  
    435.                 else  
    436.                 {  
    437.                     DebugSystem.Log("初始化资源依赖文件: Null");  
    438.                 }  
    439.                 asset.Unload(false);  
    440.                 DebugSystem.Log("初始化资源管理器全局Bundle信息成功");  
    441.                 www.Dispose();  
    442.   
    443.                 yield return InitLoadExternalStoreVersionConfig();  
    444.             }  
    445.         }  
    446.   
    447.         private IEnumerator InitLoadExternalStoreVersionConfig()  
    448.         {  
    449.             string url = AssetBundlePath.Instance.ExternalStorePathUrl + "/" + AssetBundlePath.versionConfigBundleName;  
    450.             WWW www = new WWW(url);  
    451.             yield return www;  
    452.             if (www.isDone)  
    453.             {  
    454.                 if (!string.IsNullOrEmpty(www.error))  
    455.                 {  
    456.                     DebugSystem.LogError("www Load Error:" + www.error);  
    457.                     www.Dispose();  
    458.                     yield break;  
    459.                 }  
    460.             }  
    461.             AssetBundle mConfigBundle = www.assetBundle;  
    462.             TextAsset mVersionConfig = mConfigBundle.LoadAsset<TextAsset>(AssetBundlePath.versionConfigAssetName);  
    463.             VersionId = GetVersionIdByParseXML(mVersionConfig);  
    464.             DebugSystem.Log("当前版本号:"+VersionId);  
    465.             mConfigBundle.Unload(false);  
    466.             www.Dispose();  
    467.         }  
    468.   
    469.         private int GetVersionIdByParseXML(TextAsset mTextAsset)  
    470.         {  
    471.             XmlDocument mdoc = new XmlDocument();  
    472.             mdoc.LoadXml(mTextAsset.text);  
    473.             foreach (XmlNode v in mdoc.ChildNodes)  
    474.             {  
    475.                 if (v.Name == "root")  
    476.                 {  
    477.                     foreach (XmlNode x in v.ChildNodes)  
    478.                     {  
    479.                         if (x.Name.Contains("versionId"))  
    480.                         {  
    481.                             return int.Parse(x.InnerText);  
    482.                         }  
    483.                     }  
    484.                 }  
    485.             }  
    486.             return 0;  
    487.         }  
    488.     }  
    489.   
    490.     public class AssetBundleInfo  
    491.     {  
    492.         public string bundleName;  
    493.         public Hash128 mHash;  
    494.         public string[] mDependentBundleList;  
    495.   
    496.         public AssetBundleInfo(string bundleName, Hash128 mHash128, string[] mDependentBundleList)  
    497.         {  
    498.             this.bundleName = bundleName;  
    499.             this.mHash = mHash128;  
    500.             this.mDependentBundleList = mDependentBundleList;  
    501.         }  
    502.   
    503.     }  
    504.   
    505.     public class AssetInfo  
    506.     {  
    507.         public string bundleName;  
    508.         public string assetName;  
    509.         public string assetPath;  
    510.   
    511.         public AssetInfo(string assetPath,string bundleName, string assetName)  
    512.         {  
    513.             this.assetPath = assetPath;  
    514.             this.bundleName = bundleName;  
    515.             this.assetName = assetName;  
    516.         }  
    517.   
    518.         public AssetInfo(string bundleName, string assetName)  
    519.         {  
    520.             this.bundleName = bundleName;  
    521.             this.assetName = assetName;  
    522.         }  
    523.     }  
    524.   
    525.     public class AssetBundlePath : Singleton<AssetBundlePath>  
    526.     {  
    527.         public const string versionConfigBundleName = "version.xk_unity3d";  
    528.         public const string versionConfigAssetName = "version.xml";  
    529.         public const string AssetDependentFileBundleName = "StreamingAssets";  
    530.         public const string AssetDependentFileAssetName = "AssetBundleManifest";  
    531.         public const string ABExtention = ".xk_unity3d";  
    532.   
    533.         public readonly string StreamingAssetPathUrl;  
    534.         public readonly string ExternalStorePathUrl;  
    535.         public readonly string WebServerPathUrl;  
    536.   
    537.         public readonly string ExternalStorePath;  
    538.         public AssetBundlePath()  
    539.         {  
    540.             if (Application.platform == RuntimePlatform.WindowsEditor)  
    541.             {  
    542.                 WebServerPathUrl = "file:///F:/WebServer";  
    543.                 StreamingAssetPathUrl = "file:///" + Application.streamingAssetsPath;  
    544.                 ExternalStorePathUrl = "file:///" + Application.persistentDataPath;  
    545.                 ExternalStorePath = Application.persistentDataPath;  
    546.             } else if (Application.platform == RuntimePlatform.WindowsPlayer)  
    547.             {  
    548.                 WebServerPathUrl = "file:///F:/WebServer";  
    549.                 StreamingAssetPathUrl = "file:///" + Application.streamingAssetsPath;  
    550.                 ExternalStorePathUrl = "file:///" + Application.persistentDataPath;  
    551.                 ExternalStorePath = Application.persistentDataPath;  
    552.             }else if(Application.platform == RuntimePlatform.Android)  
    553.             {  
    554.                 WebServerPathUrl = "file:///F:/WebServer";  
    555.                 StreamingAssetPathUrl = "jar:file://" + Application.dataPath + "!/assets";  
    556.                 ExternalStorePathUrl = "file://" + Application.persistentDataPath;  
    557.                 ExternalStorePath = Application.persistentDataPath;  
    558.             }  
    559.             DebugSystem.LogError("www server path: " + WebServerPathUrl);  
    560.             DebugSystem.LogError("www local Stream Path: " + StreamingAssetPathUrl);  
    561.             DebugSystem.LogError("www local external Path: " + ExternalStorePathUrl);  
    562.         }  
    563.     }  
    564.   
    565. }  
    3:加载完本地的Bundle文件,那么现在我们开始下载Web服务器上的Bundle文件:
    注意:本来我是自己定义一个md5配置文件专门用来比对资源,后来发现,Unity已经帮我们实现了这个功能。这个关键点就在于AssetBundleManifest类,具体请参考这篇文章末尾所讲的资源依赖配置文件:http://liweizhaolili.blog.163.com/blog/static/16230744201541410275298/
    下载Web服务器资源代码如下:
    [csharp] view plain copy
    1. using UnityEngine;  
    2. using System.Collections;  
    3. using xk_System.Debug;  
    4. using System.Collections.Generic;  
    5. using xk_System.AssetPackage;  
    6. using System.IO;  
    7. using System.Xml;  
    8.   
    9. namespace xk_System.HotUpdate  
    10. {  
    11.     public class AssetBundleHotUpdateManager : Singleton<AssetBundleHotUpdateManager>  
    12.     {  
    13.         private int mStreamFolderVersionId=-1;  
    14.         private int mExternalStoreVersionId=-1;  
    15.         private int mWebServerVersionId=-1;  
    16.   
    17.         private List<AssetBundleInfo> mExternalStoreABInfoList = new List<AssetBundleInfo>();  
    18.         private List<AssetBundleInfo> mWebServerABInfoList = new List<AssetBundleInfo>();  
    19.         private List<AssetBundleInfo> mStreamFolderABInfoList = new List<AssetBundleInfo>();  
    20.   
    21.         private DownLoadAssetInfo mDownLoadAssetInfo = new DownLoadAssetInfo();  
    22.   
    23.         public LoadProgressInfo mTask = new LoadProgressInfo();  
    24.   
    25.         public IEnumerator CheckUpdate()  
    26.         {  
    27.             mTask.progress = 0;  
    28.             mTask.Des = "正在检查资源";  
    29.             yield return CheckVersionConfig();  
    30.             if (mDownLoadAssetInfo.mAssetNameList.Count > 0)  
    31.             {  
    32.                 mTask.progress += 10;  
    33.                 mTask.Des = "正在下载资源";  
    34.                 yield return DownLoadAllNeedUpdateBundle();  
    35.             }  
    36.             else  
    37.             {  
    38.                 mTask.progress = 100;  
    39.             }  
    40.         }  
    41.   
    42.         /// <summary>  
    43.         /// 检查版本配置文件  
    44.         /// </summary>  
    45.         /// <returns></returns>  
    46.         private IEnumerator CheckVersionConfig()  
    47.         {  
    48.             yield return InitLoadExternalStoreVersionConfig();  
    49.             yield return InitLoadStreamFolderVersionConfig();  
    50.             yield return InitLoadWebServerVersionConfig();  
    51.   
    52.             DebugSystem.Log("本地版本号:" + mExternalStoreVersionId);  
    53.             DebugSystem.Log("WebServer版本号:" + mWebServerVersionId);  
    54.             DebugSystem.Log("StreamFolder版本号:" + mStreamFolderVersionId);  
    55.             if (mWebServerVersionId > mExternalStoreVersionId)  
    56.             {  
    57.                 yield return InitLoadExternalStoreABConfig();  
    58.                 if (mWebServerVersionId > mStreamFolderVersionId)  
    59.                 {  
    60.                     yield return InitLoadWebServerABConfig();  
    61.                     CheckAssetInfo(AssetBundlePath.Instance.WebServerPathUrl, mWebServerABInfoList);  
    62.                 }  
    63.                 else  
    64.                 {  
    65.                     yield return InitLoadStreamFolderABConfig();  
    66.                     CheckAssetInfo(AssetBundlePath.Instance.StreamingAssetPathUrl, mStreamFolderABInfoList);  
    67.                 }  
    68.             }  
    69.             else if (mStreamFolderVersionId > mExternalStoreVersionId)  
    70.             {  
    71.                 yield return InitLoadExternalStoreABConfig();  
    72.                 yield return InitLoadStreamFolderABConfig();  
    73.                 CheckAssetInfo(AssetBundlePath.Instance.StreamingAssetPathUrl, mStreamFolderABInfoList);  
    74.             }  
    75.         }  
    76.   
    77.         /// <summary>  
    78.         /// 检查资源配置文件  
    79.         /// </summary>  
    80.         /// <returns></returns>  
    81.         private void CheckAssetInfo(string url, List<AssetBundleInfo> mUpdateABInfoList)  
    82.         {  
    83.             mDownLoadAssetInfo.url = url;  
    84.             foreach (AssetBundleInfo k in mUpdateABInfoList)  
    85.             {  
    86.                 AssetBundleInfo mBundleInfo = mExternalStoreABInfoList.Find((x) =>  
    87.                 {  
    88.                     if (x.mHash.isValid && k.mHash.isValid)  
    89.                     {  
    90.                         return x.mHash.Equals(k.mHash);  
    91.                     }  
    92.                     else  
    93.                     {  
    94.                         DebugSystem.LogError("Hash is no Valid");  
    95.                         return false;  
    96.                     }  
    97.                 });  
    98.                 if (mBundleInfo == null)  
    99.                 {  
    100.                     mDownLoadAssetInfo.mAssetNameList.Add(k.bundleName);  
    101.                 }  
    102.             }  
    103.             if (mDownLoadAssetInfo.mAssetNameList.Count > 0)  
    104.             {  
    105.                 mDownLoadAssetInfo.mAssetNameList.Add(AssetBundlePath.AssetDependentFileBundleName);  
    106.             }  
    107.             DebugSystem.Log("需要下载更新的个数:" + mDownLoadAssetInfo.mAssetNameList.Count);  
    108.         }  
    109.   
    110.         private IEnumerator InitLoadWebServerVersionConfig()  
    111.         {  
    112.             string url = AssetBundlePath.Instance.WebServerPathUrl + "/" + AssetBundlePath.versionConfigBundleName;  
    113.             WWW www = new WWW(url);  
    114.             yield return www;  
    115.             if (www.isDone)  
    116.             {  
    117.                 if (!string.IsNullOrEmpty(www.error))  
    118.                 {  
    119.                     DebugSystem.LogError("www Load Error:" + www.error);  
    120.                     www.Dispose();  
    121.                     yield break;  
    122.                 }  
    123.             }  
    124.   
    125.             AssetBundle mConfigBundle = www.assetBundle;  
    126.             TextAsset mVersionConfig = mConfigBundle.LoadAsset<TextAsset>(AssetBundlePath.versionConfigAssetName);  
    127.             mWebServerVersionId = ParseXML(mVersionConfig);  
    128.             mConfigBundle.Unload(false);  
    129.             www.Dispose();  
    130.         }  
    131.   
    132.         private IEnumerator InitLoadExternalStoreVersionConfig()  
    133.         {  
    134.             string url = AssetBundlePath.Instance.ExternalStorePathUrl + "/" + AssetBundlePath.versionConfigBundleName;  
    135.             WWW www = new WWW(url);  
    136.             yield return www;  
    137.             if (www.isDone)  
    138.             {  
    139.                 if (!string.IsNullOrEmpty(www.error))  
    140.                 {  
    141.                     DebugSystem.LogError("www Load Error:" + www.error);  
    142.                     www.Dispose();  
    143.                     yield break;  
    144.                 }  
    145.             }  
    146.             AssetBundle mConfigBundle = www.assetBundle;  
    147.             TextAsset mVersionConfig = mConfigBundle.LoadAsset<TextAsset>(AssetBundlePath.versionConfigAssetName);  
    148.             mExternalStoreVersionId = ParseXML(mVersionConfig);  
    149.             mConfigBundle.Unload(false);  
    150.             www.Dispose();  
    151.         }  
    152.   
    153.         private IEnumerator InitLoadStreamFolderVersionConfig()  
    154.         {  
    155.             string url = AssetBundlePath.Instance.StreamingAssetPathUrl + "/" + AssetBundlePath.versionConfigBundleName;  
    156.             WWW www = new WWW(url);  
    157.             yield return www;  
    158.             if (www.isDone)  
    159.             {  
    160.                 if (!string.IsNullOrEmpty(www.error))  
    161.                 {  
    162.                     DebugSystem.LogError("www Load Error:" + www.error);  
    163.                     www.Dispose();  
    164.                     yield break;  
    165.                 }  
    166.             }  
    167.             AssetBundle mConfigBundle = www.assetBundle;  
    168.             TextAsset mVersionConfig = mConfigBundle.LoadAsset<TextAsset>(AssetBundlePath.versionConfigAssetName);  
    169.             mStreamFolderVersionId = ParseXML(mVersionConfig);  
    170.             mConfigBundle.Unload(false);  
    171.             www.Dispose();  
    172.         }  
    173.   
    174.         private IEnumerator InitLoadWebServerABConfig()  
    175.         {  
    176.             string url = AssetBundlePath.Instance.WebServerPathUrl + "/" + AssetBundlePath.AssetDependentFileBundleName;  
    177.             WWW www = new WWW(url);  
    178.             yield return www;  
    179.             if (www.isDone)  
    180.             {  
    181.                 if (!string.IsNullOrEmpty(www.error))  
    182.                 {  
    183.                     DebugSystem.LogError("www Load Error:" + www.error);  
    184.                     www.Dispose();  
    185.                     yield break;  
    186.                 }  
    187.             }  
    188.             AssetBundle mConfigBundle = www.assetBundle;  
    189.             AssetBundleManifest mAllBundleMainifest = mConfigBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");  
    190.             if (mAllBundleMainifest == null)  
    191.             {  
    192.                 DebugSystem.LogError("Mainifest is Null");  
    193.                 www.Dispose();  
    194.                 yield break;  
    195.             }  
    196.             string[] mAssetNames = mAllBundleMainifest.GetAllAssetBundles();  
    197.             if (mAssetNames != null)  
    198.             {  
    199.                 foreach (var v in mAssetNames)  
    200.                 {  
    201.                     string bundleName = v;  
    202.                     string[] bundleDependentList = mAllBundleMainifest.GetAllDependencies(v);  
    203.                     Hash128 mHash = mAllBundleMainifest.GetAssetBundleHash(v);  
    204.                     AssetBundleInfo mABInfo = new AssetBundleInfo(bundleName, mHash, bundleDependentList);  
    205.                     mWebServerABInfoList.Add(mABInfo);  
    206.                 }  
    207.             }  
    208.             else  
    209.             {  
    210.                 DebugSystem.Log("初始化资源依赖文件: Null");  
    211.             }  
    212.             mConfigBundle.Unload(false);  
    213.             www.Dispose();  
    214.         }  
    215.   
    216.         private IEnumerator InitLoadExternalStoreABConfig()  
    217.         {  
    218.             string url = AssetBundlePath.Instance.ExternalStorePathUrl + "/" + AssetBundlePath.AssetDependentFileBundleName;  
    219.             WWW www = new WWW(url);  
    220.             yield return www;  
    221.             if (www.isDone)  
    222.             {  
    223.                 if (!string.IsNullOrEmpty(www.error))  
    224.                 {  
    225.                     DebugSystem.LogError("www Load Error:" + www.error);  
    226.                     www.Dispose();  
    227.                     yield break;  
    228.                 }  
    229.             }  
    230.             AssetBundle mConfigBundle = www.assetBundle;  
    231.             AssetBundleManifest mAllBundleMainifest = mConfigBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");  
    232.             if (mAllBundleMainifest == null)  
    233.             {  
    234.                 DebugSystem.LogError("Mainifest is Null");  
    235.                 www.Dispose();  
    236.                 yield break;  
    237.             }  
    238.             string[] mAssetNames = mAllBundleMainifest.GetAllAssetBundles();  
    239.             if (mAssetNames != null)  
    240.             {  
    241.                 foreach (var v in mAssetNames)  
    242.                 {  
    243.                     string bundleName = v;  
    244.                     string[] bundleDependentList = mAllBundleMainifest.GetAllDependencies(v);  
    245.                     Hash128 mHash = mAllBundleMainifest.GetAssetBundleHash(v);  
    246.                     AssetBundleInfo mABInfo = new AssetBundleInfo(bundleName, mHash, bundleDependentList);  
    247.                     mExternalStoreABInfoList.Add(mABInfo);  
    248.                 }  
    249.             }  
    250.             else  
    251.             {  
    252.                 DebugSystem.Log("初始化资源依赖文件: Null");  
    253.             }  
    254.             mConfigBundle.Unload(false);  
    255.             www.Dispose();  
    256.         }  
    257.   
    258.         private IEnumerator InitLoadStreamFolderABConfig()  
    259.         {  
    260.             string url = AssetBundlePath.Instance.StreamingAssetPathUrl + "/" + AssetBundlePath.AssetDependentFileBundleName;  
    261.             WWW www = new WWW(url);  
    262.             yield return www;  
    263.             if (www.isDone)  
    264.             {  
    265.                 if (!string.IsNullOrEmpty(www.error))  
    266.                 {  
    267.                     DebugSystem.LogError("www Load Error:" + www.error);  
    268.                     www.Dispose();  
    269.                     yield break;  
    270.                 }  
    271.             }  
    272.             AssetBundle mConfigBundle = www.assetBundle;  
    273.             AssetBundleManifest mAllBundleMainifest = mConfigBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");  
    274.             if (mAllBundleMainifest == null)  
    275.             {  
    276.                 DebugSystem.LogError("Mainifest is Null");  
    277.                 www.Dispose();  
    278.                 yield break;  
    279.             }  
    280.             string[] mAssetNames = mAllBundleMainifest.GetAllAssetBundles();  
    281.             if (mAssetNames != null)  
    282.             {  
    283.                 foreach (var v in mAssetNames)  
    284.                 {  
    285.                     string bundleName = v;  
    286.                     string[] bundleDependentList = mAllBundleMainifest.GetAllDependencies(v);  
    287.                     Hash128 mHash = mAllBundleMainifest.GetAssetBundleHash(v);  
    288.                     AssetBundleInfo mABInfo = new AssetBundleInfo(bundleName, mHash, bundleDependentList);  
    289.                     mStreamFolderABInfoList.Add(mABInfo);  
    290.                 }  
    291.             }  
    292.             else  
    293.             {  
    294.                 DebugSystem.Log("初始化资源依赖文件: Null");  
    295.             }  
    296.             mConfigBundle.Unload(false);  
    297.             www.Dispose();  
    298.         }  
    299.   
    300.         /// <summary>  
    301.         /// 得到版本号  
    302.         /// </summary>  
    303.         /// <param name="mbytes"></param>  
    304.         /// <returns></returns>  
    305.         public int ParseXML(TextAsset mTextAsset)  
    306.         {  
    307.             XmlDocument mdoc = new XmlDocument();  
    308.             mdoc.LoadXml(mTextAsset.text);  
    309.             foreach (XmlNode v in mdoc.ChildNodes)  
    310.             {  
    311.                 if (v.Name == "root")  
    312.                 {  
    313.                     foreach (XmlNode x in v.ChildNodes)  
    314.                     {  
    315.                         if (x.Name.Contains("versionId"))  
    316.                         {  
    317.                             return int.Parse(x.InnerText);  
    318.                         }  
    319.                     }  
    320.                 }  
    321.             }  
    322.             return 0;  
    323.         }  
    324.   
    325.         private IEnumerator DownLoadAllNeedUpdateBundle()  
    326.         {  
    327.             List<string> bundleList = mDownLoadAssetInfo.mAssetNameList;  
    328.             List<string>.Enumerator mIter = bundleList.GetEnumerator();  
    329.   
    330.             uint addPro = (uint)Mathf.CeilToInt((LoadProgressInfo.MaxProgress - mTask.progress)/(float)bundleList.Count);  
    331.             while (mIter.MoveNext())  
    332.             {  
    333.                 DebugSystem.LogError("下载的文件:" + mDownLoadAssetInfo.url + " | " + mIter.Current);  
    334.                 yield return DownLoadSingleBundle(mDownLoadAssetInfo.url, mIter.Current);  
    335.                 mTask.progress+=addPro;  
    336.             }  
    337.         }  
    338.   
    339.         private IEnumerator DownLoadSingleBundle(string path, string bundleName)  
    340.         {  
    341.             string url = path + "/" + bundleName;  
    342.             WWW www = new WWW(url);  
    343.             yield return www;  
    344.             if (www.isDone)  
    345.             {  
    346.                 if (!string.IsNullOrEmpty(www.error))  
    347.                 {  
    348.                     DebugSystem.LogError("www Load Error:" + www.error);  
    349.                     www.Dispose();  
    350.                     yield break;  
    351.                 }  
    352.             }  
    353.             string savePath = AssetBundlePath.Instance.ExternalStorePath + "/" + bundleName;  
    354.             SaveDownLoadedFile(savePath, www.bytes);  
    355.             www.Dispose();  
    356.         }  
    357.   
    358.         private void SaveDownLoadedFile(string path, byte[] mdata)  
    359.         {  
    360.             if (File.Exists(path))  
    361.             {  
    362.                 File.Delete(path);  
    363.             }  
    364.             FileInfo mFileInfo = new FileInfo(path);  
    365.             FileStream mFileStream = mFileInfo.OpenWrite();  
    366.             mFileStream.Write(mdata, 0, mdata.Length);  
    367.             mFileStream.Flush();  
    368.             mFileStream.Close();  
    369.         }  
    370.   
    371.         private class DownLoadAssetInfo  
    372.         {  
    373.             public string url;  
    374.             public List<string> mAssetNameList = new List<string>();  
    375.         }  
    376.   
    377.   
    378.     }  
    379. }  

    现在 资源管理架构设计就完了。

    二: C#反射热更新(网上热更新的传说,多数资料都是简单一笔带过)

    1:如何编译Unity代码,生成程序集:
    Unity工程本身编译的程序集会放在ProjectLibraryScriptAssemblies文件夹下,所以刚开始我是直接拿这个去加载程序集的,后来发现不行。
    因为加载的程序集,与本地程序集重名,Unity会认为加载的程序集,还是本地程序集。(测过结果就是这样)
    所以后来,通过VS2015编译Unity工程,但遇到一个问题:build的时候报了一大堆错误,错误的原因在于,Proto 生成的cs文件 所用的.net版本过高导致的。
    你可以重新新build Protobuf 源码,然后生成.net低版本的程序集,这样做是可以的。

    2:加载程序集,代码如下
    [csharp] view plain copy
    1. using UnityEngine;  
    2. using System.Collections;  
    3. using System.Reflection;  
    4. using xk_System.Debug;  
    5. using System;  
    6.   
    7. namespace xk_System.AssetPackage  
    8. {  
    9.     public class AssemblyManager : Singleton<AssemblyManager>  
    10.     {  
    11.         private Assembly mHotUpdateAssembly;  
    12.         private Assembly mCurrentAssembly;  
    13.         /// <summary>  
    14.         /// 加载程序集  
    15.         /// </summary>  
    16.         /// <returns></returns>  
    17.         public IEnumerator LoadAssembly()  
    18.         {  
    19.             AssetInfo mAssetInfo = ResourceABsFolder.Instance.scripts.mtest;  
    20.             string path = AssetBundlePath.Instance.ExternalStorePathUrl;  
    21.   
    22.             string bundleName1 = mAssetInfo.bundleName;  
    23.             string url = path + "/" + bundleName1;  
    24.             WWW www = new WWW(url);  
    25.             yield return www;  
    26.             if (www.isDone)  
    27.             {  
    28.                 if (!string.IsNullOrEmpty(www.error))  
    29.                 {  
    30.                     DebugSystem.LogError("www Load Error:" + www.error);  
    31.                     yield break;  
    32.                 }  
    33.             }  
    34.             AssetBundle mConfigBundle = www.assetBundle;  
    35.             TextAsset mAsset = mConfigBundle.LoadAsset<TextAsset>(mAssetInfo.assetName);  
    36.             mHotUpdateAssembly = Assembly.Load(mAsset.bytes);  
    37.             if (mHotUpdateAssembly != null)  
    38.             {  
    39.                 DebugSystem.Log("加载程序集:" + mHotUpdateAssembly.FullName);  
    40.             }  
    41.             else  
    42.             {  
    43.                 DebugSystem.Log("加载程序集: null");  
    44.             }  
    45.             mCurrentAssembly = this.GetType().Assembly;  
    46.             DebugSystem.Log("当前程序集:" + mCurrentAssembly.FullName);  
    47.             if (mCurrentAssembly.FullName.Equals(mHotUpdateAssembly.FullName))  
    48.             {  
    49.                 DebugSystem.LogError("加载程序集名字有误");  
    50.             }  
    51.             mConfigBundle.Unload(false);  
    52.         }  
    53.   
    54.         public object CreateInstance(string typeFullName)  
    55.         {  
    56.             if (mHotUpdateAssembly != null)  
    57.             {  
    58.                 return mHotUpdateAssembly.CreateInstance(typeFullName);  
    59.             }  
    60.             else  
    61.             {  
    62.                return mCurrentAssembly.CreateInstance(typeFullName);  
    63.             }  
    64.         }  
    65.   
    66.         /// <summary>  
    67.         /// 仅仅写入口时,调用。(否则,会使程序变得混乱,反正我是搞乱了)  
    68.         /// </summary>  
    69.         /// <param name="obj"></param>  
    70.         /// <param name="typeFullName"></param>  
    71.         /// <returns></returns>  
    72.         public Component AddComponent(GameObject obj, string typeFullName)  
    73.         {  
    74.             DebugSystem.Log("Type: " + typeFullName);  
    75.             if (mHotUpdateAssembly != null)  
    76.             {  
    77.                 Type mType = mHotUpdateAssembly.GetType(typeFullName);  
    78.                 return obj.AddComponent(mType);  
    79.             }  
    80.             else  
    81.             {  
    82.                 Type mType = typeFullName.GetType();  
    83.                 return obj.AddComponent(mType);  
    84.             }  
    85.         }  
    86.     }  
    87. }  

    3:加载完程序集后该如何使用这个程序集就是重点了。
    刚开始想这个问题的时候感觉无非反射了这么简单的问题,后来越想感觉越复杂,幸好,崩溃完了之后,发现其实,你只要遵守2点即可实现游戏代码全部更新。(1):我们前面已经做完了,加载资源和加载程序集的工作,那么我们现在要做的工作,就是实现这个新加载的程序集的入口。切记,这个入口要通过动态添加组件的方式出现。如:  
                  Type mType = mHotUpdateAssembly.GetType(typeFullName);obj.AddComponent(mType);
    (2):要注意所有的预制件上要动态添加脚本,否则,预制件会去寻找【本地程序集】的脚本添加上去,并且还会导致【本地程序集】与【热更新程序集】相互访问的问题。
    在这里要注意一点:因为我们已经提供了【热更新程序集】的入口,所以,接下来程序动态添加脚本就会使用【热更新程序集】里脚本。千万不要再去反射程序集里某某个脚本了,加载脚本,还和以前一样写就好了。如:

    obj.AddComponent<T>(); 这里与入口动态添加的方式可不一样啊。(没有反射的)。

  • 相关阅读:
    Centos 7 安装配置
    日常问题
    Fluent_Python_Part1序幕,01-data-model, 数据模型
    计算机基础
    dist-packages vs site-packages
    斗地主 (NOIP2015 Day1 T3)
    字串变换 (2002 年NOIP全国联赛提高组)
    搜索
    关于动态最大子段和--线段树查询
    Caused by: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'company' in 'class java.lang.String'
  • 原文地址:https://www.cnblogs.com/nafio/p/9136996.html
Copyright © 2020-2023  润新知