資源管理架構設計

轉自https://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文件下, 代碼以下:
  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\n{\n";
  26.  
    DirectoryInfo mDir = new DirectoryInfo(BuildAssetPath);
  27.  
    m += "\tpublic class " + mDir.Name + "Folder : Singleton<" + mDir.Name + "Folder>\n\t{\n";
  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 += "\t\t public " + fieldName + " " + v.Name + "=new " + fieldName + "();\n";
  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 += "\t}\n";
  53.  
    // m += s;
  54.  
    m += "}\n";
  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\n"+tStr+"{\n";
  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+ "\t public AssetInfo m" + fileName + "=new AssetInfo(\""+assetPath+"\",\"" + bundleName1 + "\",\"" + v.Name + "\");\n";
  87.  
    }
  88.  
    }
  89.  
    m += tStr+ "}\n";
  90.  
    }
  91.  
    else
  92.  
    {
  93.  
    if (mDir.GetDirectories().Length > 0)
  94.  
    {
  95.  
     
  96.  
    m = tStr+ "public class " + mDir.Name + "Folder\n"+tStr+"{\n";
  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+ "\t public " + fieldName + " " + v.Name + "=new " + fieldName + "();\n";
  113.  
    }
  114.  
    }
  115.  
    foreach (var v in mDir.GetDirectories())
  116.  
    {
  117.  
    m += CreateDirClass(v, bundleName + "_" + v.Name.ToLower());
  118.  
    }
  119.  
    m += tStr+ "}\n";
  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 += "\t";
  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類,這個類的目的專門用來更新完畢後,充當資源加載管理器。代碼以下
  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服務器資源代碼以下:
  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工程自己編譯的程序集會放在Project\Library\ScriptAssemblies文件夾下,因此剛開始我是直接拿這個去加載程序集的,後來發現不行。
由於加載的程序集,與本地程序集重名,Unity會認爲加載的程序集,仍是本地程序集。(測過結果就是這樣)
因此後來,經過VS2015編譯Unity工程,但遇到一個問題:build的時候報了一大堆錯誤,錯誤的緣由在於,Proto 生成的cs文件 所用的.net版本太高致使的。
你能夠從新新build Protobuf 源碼,而後生成.net低版本的程序集,這樣作是能夠的。
 
2:加載程序集,代碼以下
  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.  
    }
  88.  
    }
 
3:加載完程序集後該如何使用這個程序集就是重點了。
剛開始想這個問題的時候感受無非反射了這麼簡單的問題,後來越想感受越複雜,幸虧,崩潰完了以後,發現其實,你只要遵照2點便可實現遊戲代碼所有更新。(1):咱們前面已經作完了,加載資源和加載程序集的工做,那麼咱們如今要作的工做,就是實現這個新加載的程序集的入口。切記,這個入口要經過動態添加組件的方式出現。如:  
              Type mType = mHotUpdateAssembly.GetType(typeFullName);obj.AddComponent(mType);
(2):要注意全部的預製件上要動態添加腳本,不然,預製件會去尋找【本地程序集】的腳本添加上去,而且還會致使【本地程序集】與【熱更新程序集】相互訪問的問題。
在這裏要注意一點:由於咱們已經提供了【熱更新程序集】的入口,因此,接下來程序動態添加腳本就會使用【熱更新程序集】裏腳本。千萬不要再去反射程序集裏某某個腳本了,加載腳本,還和之前同樣寫就行了。如:
obj.AddComponent<T>(); 這裏與入口動態添加的方式可不同啊。(沒有反射的)。
相關文章
相關標籤/搜索