精华内容
下载资源
问答
  • 1·. AssetBundle 的使用流程: (1)标记 (2) Build (3) 加载 AB包 ex. LoadFromFile (4)加载资源

    1·. AssetBundle 的使用流程:
    (1)标记
    (2) Build
    (3) 加载 AB包 ex. LoadFromFile
    (4)加载资源

    展开全文
  • AssetBundle 的使用流程: (1)标记 (2) Build (3) 加载 AB包 ex. LoadFromFile (4)加载资源
    1. 卸载独立的资源: Resources.UnloadAsset(audioClip);
    IEnumerator Start()
    		{
    			var audioClip = Resources.Load<AudioClip>("coin");
    			
    			yield return new WaitForSeconds(5.0f);
    			
    			Resources.UnloadAsset(audioClip);
    			
    			Debug.Log("coin unloaded");
    		}
    
    1. 卸载不是独立的资源, Resources.UnloadUnusedAssets();
    IEnumerator Start()
    		{
    			var homePanel = Resources.Load<GameObject>("HomePanel");
    			
    			yield return new WaitForSeconds(5.0f);
    
    
    			homePanel = null;
    			
    			Resources.UnloadUnusedAssets();
    			
    			Debug.Log("homepanel unloaded");
    			
    		}
    
    1. 在一个页面打开的时候,加载资源,在一个页面关闭的时候卸载资源
      (1) 资源加载和卸载要成对使用
      (2)避免重复加载资源
      (3)避免错误的卸载掉还在使用的资源

    2. 避免重复加载资源

      private static Dictionary<string, object> AssetsDic = new Dictionary<string, object>();
    
        private T loadAsset<T>(string assetName) where T : Object
        {
            T asset = null;
            if (!AssetsDic.ContainsKey(assetName))
            {
                asset= Resources.Load<T>(assetName);
                AssetsDic.Add(assetName, asset);
            }
            else
            {
                asset = AssetsDic[assetName] as T;
            }
            return asset;      
        }
    
    1. 优化,添加资源加载的记录池
    
        private static List<string> RecordPool = new List<string>(); //记录池
        private static Dictionary<string, object> AssetsDic = new Dictionary<string, object>();   //资源池
    
        private T loadAsset<T>(string assetName) where T : Object
        {
            T asset = null;
            if (!AssetsDic.ContainsKey(assetName))
            {
                asset= Resources.Load<T>(assetName);
                AssetsDic.Add(assetName, asset);   //资源池
                RecordPool.Add(assetName);   //记录池
            }
            else
            {
                asset = AssetsDic[assetName] as T;
            }
            return asset;   
    
    展开全文
  • Unity5 AssetBundle资源管理架构设计

    千次阅读 2016-06-17 22:46:47
    Unity资源管理架构设计 安卓热更新解决方案

    本文介绍两大内容:

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

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



    一:Unity资源管理架构设计

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

    1:设计一个资源信息管理类,能够反映Assets/ResourceABs文件夹下的全部的资源信息。
    生成工具放在Editor文件下, 代码如下:
    using UnityEngine;
    using System.Collections;
    using System.IO;
    using UnityEditor;
    using xk_System.AssetPackage;
    
    public class ExportAssetInfoEditor : MonoBehaviour
    {
        static string extention = AssetBundlePath.ABExtention;
        static string BuildAssetPath = "Assets/ResourceABs";
        static string CsOutPath = "Assets/Scripts/auto";
    
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~创建AB文件所有的信息~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        [MenuItem("UnityEditor/GenerationPackage/Generation AssetInfo Cs File")]
        public static void GenericAssetCSInfo()
        {
            Debug.Log("Start Generation AssetInfo Cs Info");
            CreateABCSFile();
            Debug.Log("Finish Generation AssetInfo Cs Info");
        }
    
        private static void CreateABCSFile()
        {
            string m = "";
            m += "namespace xk_System.AssetPackage\n{\n";
            DirectoryInfo mDir = new DirectoryInfo(BuildAssetPath);
            m += "\tpublic class " + mDir.Name + "Folder : Singleton<" + mDir.Name + "Folder>\n\t{\n";
            string s = "";
            foreach (var v in mDir.GetDirectories())
            {
                FileInfo[] mFileInfos1 = v.GetFiles();
                int mFilesLength1 = 0;
                foreach (var v1 in mFileInfos1)
                {
                    if (v1.Extension != ".meta")
                    {
                        mFilesLength1++;
                        break;
                    }
                }
                if (mFilesLength1 > 0 || v.GetDirectories().Length > 0)
                {
                    string fieldName = v.Name + "Folder";
                    m += "\t\t public " + fieldName + " " + v.Name + "=new " + fieldName + "();\n";
                   // s += CreateDirClass(v, v.Name.ToLower());
                }
            }
            foreach (var v in mDir.GetDirectories())
            {
                m += CreateDirClass(v, v.Name.ToLower());
            }
            m += "\t}\n";
           // m += s;
            m += "}\n";
            string fileName = CsOutPath + "/" + mDir.Name + ".cs";
            StreamWriter mSw = new StreamWriter(fileName, false);
            mSw.Write(m);
            mSw.Close();
        }
    
        private static string CreateDirClass(DirectoryInfo mDir, string bundleName)
        {
            string tStr = GetTStr(mDir);
            string m = "";
            string s = "";
            FileInfo[] mFileInfos = mDir.GetFiles();
            int mFilesLength = 0;
            foreach (var v in mFileInfos)
            {
                if (v.Extension != ".meta")
                {
                    mFilesLength++;
                    break;
                }
            }
            if (mFilesLength > 0)
            {
                string bundleName1 = bundleName+ extention;
                m = tStr+"public class " + mDir.Name + "Folder\n"+tStr+"{\n";
                foreach (var v in mFileInfos)
                {
                    if (v.Extension != ".meta")
                    {
                        string assetPath = GetAssetPath(v.FullName);
                        string fileName = v.Name.Substring(0, v.Name.LastIndexOf(v.Extension));
                        m += tStr+"\t public AssetInfo m" + fileName + "=new AssetInfo(\""+assetPath+"\",\"" + bundleName1 + "\",\"" + v.Name + "\");\n";
                    }
                }
                m += tStr+"}\n";
            }
            else
            {
                if (mDir.GetDirectories().Length > 0)
                {
    
                    m = tStr+"public class " + mDir.Name + "Folder\n"+tStr+"{\n";
                    foreach (var v in mDir.GetDirectories())
                    {
                        FileInfo[] mFileInfos1 = v.GetFiles();
                        int mFilesLength1 = 0;
                        foreach (var v1 in mFileInfos1)
                        {
                            if (v1.Extension != ".meta")
                            {
                                mFilesLength1++;
                                break;
                            }
                        }
                        if (mFilesLength1 > 0 || v.GetDirectories().Length > 0)
                        {
                            string fieldName = v.Name + "Folder";
                            m += tStr+"\t public " + fieldName + " " + v.Name + "=new " + fieldName + "();\n";
                        }
                    }
                    foreach (var v in mDir.GetDirectories())
                    {
                        m += CreateDirClass(v, bundleName + "_" + v.Name.ToLower());
                    }
                    m += tStr+"}\n";
                   // m += s;
                }
            }
            return m;
        }
        public static string GetTStr(DirectoryInfo mDir)
        {
            int coutT = 0;
            int index = mDir.FullName.IndexOf(@"ResourceABs\");
            if (index >= 0)
            {
                for(int j=0;j<mDir.FullName.Length;j++)
                {
                    if (j > index)
                    {
                        var v = mDir.FullName[j];
                        if (v.Equals('\\'))
                        {
                            coutT++;
                        }
                    }
                }
            }
            coutT++;
            string tStr = "";
            int i = 0;
            while(i<coutT)
            {
                tStr += "\t";
                i++;
            }
            return tStr;
        }
    
        public static string GetAssetPath(string filePath)
        {
            string assetPath = "";
            int index = filePath.IndexOf(@"Assets\");
            if (index >= 0)
            {
                assetPath = filePath.Remove(0, index);
                assetPath = assetPath.Replace(@"\","/");
            }
            return assetPath;
        }
    
    }
    
    到这里,这个资源基本信息管理类就处理好了。
    2:我们就正式开始写资源管理架构类了
    我们首先写一个AssetBundleManager类,这个类的目的专门用来更新完毕后,充当资源加载管理器。代码如下
    using UnityEngine;
    using System.Collections;
    using xk_System.Debug;
    using System.Collections.Generic;
    using System.Xml;
    
    namespace xk_System.AssetPackage
    {
        /// <summary>
        /// 此类的目的就是加载本地的Bundle进行资源读取操作的
        /// </summary>
        public class AssetBundleManager : SingleTonMonoBehaviour<AssetBundleManager>
        {
            private ResourcesABManager mResourcesABManager = new ResourcesABManager();
            private Dictionary<string, AssetBundle> mBundleDic = new Dictionary<string, AssetBundle>();
            private Dictionary<string, Dictionary<string, UnityEngine.Object>> mAssetDic = new Dictionary<string, Dictionary<string, UnityEngine.Object>>();
            private List<string> mBundleLockList = new List<string>();
    
            /// <summary>
            /// 加载Assetbundle方案1:初始化时,全部加载
            /// </summary>
            /// <returns></returns>
            public IEnumerator InitLoadAllBundleFromLocal()
            {
                yield return mResourcesABManager.InitLoadMainifestFile();
                List<AssetBundleInfo> bundleList = mResourcesABManager.mNeedLoadBundleList;
                List<AssetBundleInfo>.Enumerator mIter = bundleList.GetEnumerator();
                while (mIter.MoveNext())
                {
                    yield return AsyncLoadFromLoaclSingleBundle(mIter.Current);
                }
            }
            public IEnumerator InitAssetBundleManager()
            {
                yield return mResourcesABManager.InitLoadMainifestFile();
            }
    
            private IEnumerator CheckBundleDependentBundle(AssetBundleInfo mBundle)
            {
                if (mBundle != null)
                {
                    string[] mdependentBundles = mBundle.mDependentBundleList;
                    foreach (string s in mdependentBundles)
                    {
                        AssetBundleInfo mBundleInfo = mResourcesABManager.GetBundleInfo(s);
                        if (mBundleInfo != null)
                        {
                            AssetBundle mAB = null;
                            if (!mBundleDic.TryGetValue(mBundleInfo.bundleName, out mAB))
                            {
                                yield return AsyncLoadFromLoaclSingleBundle(mBundleInfo);
                            }
                            else
                            {
                                if (mAB == null)
                                {
                                    yield return AsyncLoadFromLoaclSingleBundle(mBundleInfo);
                                }
                            }
                        }
                    }
                }
            }
            /// <summary>
            /// 从本地外部存储位置加载单个Bundle资源,全部加载
            /// </summary>
            /// <param name="BaseBundleInfo"></param>
            /// <returns></returns>
            private IEnumerator AsyncLoadFromLoaclSingleBundle1(AssetBundleInfo BaseBundleInfo)
            {
                if(mBundleLockList.Contains(BaseBundleInfo.bundleName))
                {
                    while(mBundleLockList.Contains(BaseBundleInfo.bundleName))
                    {
                        yield return null;
                    }
                    yield break;
                }     
                mBundleLockList.Add(BaseBundleInfo.bundleName);
                yield return CheckBundleDependentBundle(BaseBundleInfo);
                string path = AssetBundlePath.Instance.ExternalStorePathUrl;
                string url = path + "/" + BaseBundleInfo.bundleName;
                WWW www = new WWW(url);
                yield return www;
                if (www.isDone)
                {
                    if (!string.IsNullOrEmpty(www.error))
                    {
                        DebugSystem.LogError("www Load Error:" + www.error);
                        www.Dispose();
                        mBundleLockList.Remove(BaseBundleInfo.bundleName);
                        yield break;
                    }
                }
                AssetBundle asset = www.assetBundle;
                SaveBundleToDic(BaseBundleInfo.bundleName, asset);
                mBundleLockList.Remove(BaseBundleInfo.bundleName);
                www.Dispose();
            }
    
            /// <summary>
            /// 从本地外部存储位置加载单个Bundle资源,全部加载
            /// </summary>
            /// <param name="BaseBundleInfo"></param>
            /// <returns></returns>
            private IEnumerator AsyncLoadFromLoaclSingleBundle(AssetBundleInfo BaseBundleInfo)
            {
                if (mBundleLockList.Contains(BaseBundleInfo.bundleName))
                {
                    while (mBundleLockList.Contains(BaseBundleInfo.bundleName))
                    {
                        yield return null;
                    }
                    yield break;
                }
                mBundleLockList.Add(BaseBundleInfo.bundleName);
                yield return CheckBundleDependentBundle(BaseBundleInfo);
                string path = AssetBundlePath.Instance.ExternalStorePath+"/"+BaseBundleInfo.bundleName;
                AssetBundleCreateRequest www= AssetBundle.LoadFromFileAsync(path);
                www.allowSceneActivation = true;
                yield return www;
                AssetBundle asset = www.assetBundle;
                SaveBundleToDic(BaseBundleInfo.bundleName, asset);
                mBundleLockList.Remove(BaseBundleInfo.bundleName);
            }
            /// <summary>
            /// 异步从本地外部存储加载单个Asset文件,只加载Bundle中的单个资源
            /// </summary>
            /// <param name="bundle"></param>
            /// <returns></returns>
            private IEnumerator AsyncLoadFromLocalSingleAsset(AssetBundleInfo bundle, string assetName)
            {
                if (bundle != null)
                {
                    yield return AsyncLoadFromLoaclSingleBundle(bundle);
                    UnityEngine.Object Obj = mBundleDic[bundle.bundleName].LoadAsset(assetName);
                    if (Obj != null)
                    {
                        DebugSystem.Log("Async Load Asset Success:" + Obj.name);
                        SaveAssetToDic(bundle.bundleName, assetName, Obj);
                    }
                }
            }
            /// <summary>
            /// 同步从本地外部存储加载单个Bundle文件
            /// </summary>
            /// <param name="BaseBundleInfo"></param>
            /// <param name="assetName"></param>
            /// <returns></returns>
            private void SyncLoadFromLocalSingleBundle(string bundleName)
            {
                if (!JudegeOrExistBundle(bundleName))
                {
                    string path = AssetBundlePath.Instance.ExternalStorePath + "/" + bundleName;
                    AssetBundle asset = AssetBundle.LoadFromFile(path);
                    SaveBundleToDic(bundleName, asset);
                }else
                {
                    DebugSystem.LogError("Bundle 已存在:"+bundleName);
                }
            }
    
            /// <summary>
            /// 同步从本地外部存储加载单个资源文件
            /// </summary>
            /// <param name="BaseBundleInfo"></param>
            /// <param name="assetName"></param>
            /// <returns></returns>
            public UnityEngine.Object SyncLoadFromLocalSingleAsset(AssetInfo mAssetInfo)
            {
                if (!JudgeOrExistAsset(mAssetInfo.bundleName, mAssetInfo.assetName))
                {
                    string path = AssetBundlePath.Instance.ExternalStorePath+"/"+mAssetInfo.bundleName;
                    AssetBundle asset = AssetBundle.LoadFromFile(path);
                    SaveBundleToDic(mAssetInfo.bundleName,asset);
                }
                return GetAssetFromDic(mAssetInfo.bundleName,mAssetInfo.assetName);
            }
    
    
            private void SaveBundleToDic(string bundleName, AssetBundle bundle)
            {
                if (bundle == null)
                {
                    DebugSystem.LogError("未保存的Bundle为空:"+bundleName);
                    return;
                }
                if (!mBundleDic.ContainsKey(bundleName))
                {
                    mBundleDic[bundleName] = bundle;
                }else
                {
                    DebugSystem.LogError("Bundle资源 重复:"+bundleName);
                }
            }
    
            private void SaveAssetToDic(string bundleName, string assetName, UnityEngine.Object asset)
            {
                if (asset == null)
                {
                    DebugSystem.LogError("未保存的资源为空:"+assetName);
                    return;
                }
                if(asset is GameObject)
                {
                    GameObject obj = asset as GameObject;
                    obj.SetActive(false);
                }
                if (!mAssetDic.ContainsKey(bundleName))
                {
                    Dictionary<string, UnityEngine.Object> mDic = new Dictionary<string, UnityEngine.Object>();
                    mAssetDic.Add(bundleName, mDic);
                }
                mAssetDic[bundleName][assetName] = asset;
            }
    
            private bool JudgeOrBundelIsLoading(string bundleName)
            {
                if (mBundleLockList.Contains(bundleName))
                {
                    return true;
                }else
                {
                    return false;
                }
            }
    
            private bool JudegeOrExistBundle(string bundleName)
            {
                if (mBundleDic.ContainsKey(bundleName) && mBundleDic[bundleName] != null)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
    
            private bool JudgeOrExistAsset(string bundleName, string asstName)
            {
                if (JudegeOrExistBundle(bundleName))
                {
                    if (!mAssetDic.ContainsKey(bundleName) || mAssetDic[bundleName] == null || !mAssetDic[bundleName].ContainsKey(asstName) || mAssetDic[bundleName][asstName] == null)
                    {
                        UnityEngine.Object mm = mBundleDic[bundleName].LoadAsset(asstName);
                        if (mm != null)
                        {
                            SaveAssetToDic(bundleName, asstName, mm);
                            return true;
                        }
                        else
                        {
                            return false;
                        }
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            }
    
            private UnityEngine.Object GetAssetFromDic(string bundleName, string asstName)
            {
                if (JudgeOrExistAsset(bundleName, asstName))
                {
                    UnityEngine.Object mAsset1 = mAssetDic[bundleName][asstName];
                    if (mAsset1 is GameObject)
                    {
                        GameObject obj = Instantiate(mAsset1) as GameObject;
                        return obj;
                    }
                    else
                    {
                        return mAsset1;
                    }
                }
                else
                {
                    DebugSystem.LogError("Asset is NUll:" + asstName);
                }
                return null;
            }
    #if UNITY_EDITOR
            private Dictionary<string, UnityEngine.Object> mEditorAssetDic = new Dictionary<string, UnityEngine.Object>();
    
            private UnityEngine.Object GetAssetFromEditorDic(string assetPath)
            {
                if (string.IsNullOrEmpty(assetPath))
                {
                    DebugSystem.LogError("Editor AssetPath is Empty");
                    return null;
                }
                UnityEngine.Object asset = null;
                if (!mEditorAssetDic.TryGetValue(assetPath, out asset))
                {
                    asset = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath);
                    if (asset != null)
                    {
                        if (asset is GameObject)
                        {
                            GameObject obj = asset as GameObject;
                            obj.SetActive(false);
                        }
                        mEditorAssetDic.Add(assetPath, asset);
                    }
                    else
                    {
                        DebugSystem.LogError("找不到资源:" + assetPath);
                    }
                }
                if (asset is GameObject)
                {
                    GameObject obj = Instantiate(asset) as GameObject;
                    return obj;
                }
                else
                {
                    return asset;
                }
            }
    #endif
            public IEnumerator AsyncLoadBundle(string bundleName)
            {
                if (!JudegeOrExistBundle(bundleName))
                {
                    string path = AssetBundlePath.Instance.ExternalStorePath + "/" + bundleName;
                    AssetBundle asset = AssetBundle.LoadFromFile(path);
                    SaveBundleToDic(bundleName, asset);
                    yield return null;
                }          
            }
            /// <summary>
            /// 这个东西用来在顶层使用
            /// </summary>
            /// <param name="type"></param>
            /// <param name="assetName"></param>
            /// <returns></returns>
            public UnityEngine.Object LoadAsset(AssetInfo mAssetInfo)
            {
                if (GameConfig.Instance.orUseAssetBundle)
                {
                    return GetAssetFromDic(mAssetInfo.bundleName, mAssetInfo.assetName);
                }
                else
                {
                   return GetAssetFromEditorDic(mAssetInfo.assetPath);
                }
            }
    
            /// <summary>
            /// 这个东西用来在专门的管理器中使用(底层封装一下),禁止在顶层使用
            /// </summary>
            /// <param name="type"></param>
            /// <param name="assetName"></param>
            /// <returns></returns>
            public IEnumerator AsyncLoadAsset(AssetInfo mAssetInfo)
            {
                if (GameConfig.Instance.orUseAssetBundle)
                {
                    string bundleName = mAssetInfo.bundleName;
                    string asstName = mAssetInfo.assetPath;
                    if (!JudgeOrExistAsset(bundleName, asstName))
                    {
                        yield return AsyncLoadFromLocalSingleAsset(mResourcesABManager.GetBundleInfo(bundleName), asstName);
                    }
                }
            }
        }
    
        public class ResourcesABManager
        {
            public int VersionId = -1;
            public List<AssetBundleInfo> mNeedLoadBundleList = new List<AssetBundleInfo>();
            public AssetBundleInfo GetBundleInfo(string bundleName)
            {
                AssetBundleInfo mBundleInfo = mNeedLoadBundleList.Find((x) =>
                {
                    return x.bundleName == bundleName;
                });
                return mBundleInfo;
            }
    
            public IEnumerator InitLoadMainifestFile()
            {
                if (mNeedLoadBundleList.Count == 0)
                {
                    string path = AssetBundlePath.Instance.ExternalStorePathUrl;
                    string url = path + "/" + AssetBundlePath.AssetDependentFileBundleName;
                    WWW www = new WWW(url);
                    yield return www;
                    if (www.isDone)
                    {
                        if (!string.IsNullOrEmpty(www.error))
                        {
                            DebugSystem.LogError("初始化 MainifestFile 失败:" + www.error);
                            www.Dispose();
                            yield break;
                        }
                    }
                    AssetBundle asset = www.assetBundle;
                    www.Dispose();
                    if (asset == null)
                    {
                        DebugSystem.LogError("MainifestFile Bundle is Null");
                        www.Dispose();
                        yield break;
                    }
    
                    AssetBundleManifest mAllBundleMainifest = asset.LoadAsset<AssetBundleManifest>(AssetBundlePath.AssetDependentFileAssetName);
                    if (mAllBundleMainifest == null)
                    {
                        DebugSystem.LogError("Mainifest is Null");
                        www.Dispose();
                        yield break;
                    }
                    string[] mAssetNames = mAllBundleMainifest.GetAllAssetBundles();
                    if (mAssetNames != null)
                    {
                        foreach (var v in mAssetNames)
                        {
    
                            string bundleName = v;
                            string[] bundleDependentList = mAllBundleMainifest.GetAllDependencies(v);
                            Hash128 mHash = mAllBundleMainifest.GetAssetBundleHash(v);
                            AssetBundleInfo mABInfo = new AssetBundleInfo(bundleName, mHash, bundleDependentList);
                            mNeedLoadBundleList.Add(mABInfo);
                        }
                    }
                    else
                    {
                        DebugSystem.Log("初始化资源依赖文件: Null");
                    }
                    asset.Unload(false);
                    DebugSystem.Log("初始化资源管理器全局Bundle信息成功");
                    www.Dispose();
    
                    yield return InitLoadExternalStoreVersionConfig();
                }
            }
    
            private IEnumerator InitLoadExternalStoreVersionConfig()
            {
                string url = AssetBundlePath.Instance.ExternalStorePathUrl + "/" + AssetBundlePath.versionConfigBundleName;
                WWW www = new WWW(url);
                yield return www;
                if (www.isDone)
                {
                    if (!string.IsNullOrEmpty(www.error))
                    {
                        DebugSystem.LogError("www Load Error:" + www.error);
                        www.Dispose();
                        yield break;
                    }
                }
                AssetBundle mConfigBundle = www.assetBundle;
                TextAsset mVersionConfig = mConfigBundle.LoadAsset<TextAsset>(AssetBundlePath.versionConfigAssetName);
                VersionId = GetVersionIdByParseXML(mVersionConfig);
                DebugSystem.Log("当前版本号:"+VersionId);
                mConfigBundle.Unload(false);
                www.Dispose();
            }
    
            private int GetVersionIdByParseXML(TextAsset mTextAsset)
            {
                XmlDocument mdoc = new XmlDocument();
                mdoc.LoadXml(mTextAsset.text);
                foreach (XmlNode v in mdoc.ChildNodes)
                {
                    if (v.Name == "root")
                    {
                        foreach (XmlNode x in v.ChildNodes)
                        {
                            if (x.Name.Contains("versionId"))
                            {
                                return int.Parse(x.InnerText);
                            }
                        }
                    }
                }
                return 0;
            }
        }
    
        public class AssetBundleInfo
        {
            public string bundleName;
            public Hash128 mHash;
            public string[] mDependentBundleList;
    
            public AssetBundleInfo(string bundleName, Hash128 mHash128, string[] mDependentBundleList)
            {
                this.bundleName = bundleName;
                this.mHash = mHash128;
                this.mDependentBundleList = mDependentBundleList;
            }
    
        }
    
        public class AssetInfo
        {
            public string bundleName;
            public string assetName;
            public string assetPath;
    
            public AssetInfo(string assetPath,string bundleName, string assetName)
            {
                this.assetPath = assetPath;
                this.bundleName = bundleName;
                this.assetName = assetName;
            }
    
            public AssetInfo(string bundleName, string assetName)
            {
                this.bundleName = bundleName;
                this.assetName = assetName;
            }
        }
    
        public class AssetBundlePath : Singleton<AssetBundlePath>
        {
            public const string versionConfigBundleName = "version.xk_unity3d";
            public const string versionConfigAssetName = "version.xml";
            public const string AssetDependentFileBundleName = "StreamingAssets";
            public const string AssetDependentFileAssetName = "AssetBundleManifest";
            public const string ABExtention = ".xk_unity3d";
    
            public readonly string StreamingAssetPathUrl;
            public readonly string ExternalStorePathUrl;
            public readonly string WebServerPathUrl;
    
            public readonly string ExternalStorePath;
            public AssetBundlePath()
            {
                if (Application.platform == RuntimePlatform.WindowsEditor)
                {
                    WebServerPathUrl = "file:///F:/WebServer";
                    StreamingAssetPathUrl = "file:///" + Application.streamingAssetsPath;
                    ExternalStorePathUrl = "file:///" + Application.persistentDataPath;
                    ExternalStorePath = Application.persistentDataPath;
                } else if (Application.platform == RuntimePlatform.WindowsPlayer)
                {
                    WebServerPathUrl = "file:///F:/WebServer";
                    StreamingAssetPathUrl = "file:///" + Application.streamingAssetsPath;
                    ExternalStorePathUrl = "file:///" + Application.persistentDataPath;
                    ExternalStorePath = Application.persistentDataPath;
                }else if(Application.platform == RuntimePlatform.Android)
                {
                    WebServerPathUrl = "file:///F:/WebServer";
                    StreamingAssetPathUrl = "jar:file://" + Application.dataPath + "!/assets";
                    ExternalStorePathUrl = "file://" + Application.persistentDataPath;
                    ExternalStorePath = Application.persistentDataPath;
                }
                DebugSystem.LogError("www server path: " + WebServerPathUrl);
                DebugSystem.LogError("www local Stream Path: " + StreamingAssetPathUrl);
                DebugSystem.LogError("www local external Path: " + ExternalStorePathUrl);
            }
        }
    
    }
    3:加载完本地的Bundle文件,那么现在我们开始下载Web服务器上的Bundle文件:
    注意:本来我是自己定义一个md5配置文件专门用来比对资源,后来发现,Unity已经帮我们实现了这个功能。这个关键点就在于AssetBundleManifest类,具体请参考这篇文章末尾所讲的资源依赖配置文件:http://liweizhaolili.blog.163.com/blog/static/16230744201541410275298/
    下载Web服务器资源代码如下:
    using UnityEngine;
    using System.Collections;
    using xk_System.Debug;
    using System.Collections.Generic;
    using xk_System.AssetPackage;
    using System.IO;
    using System.Xml;
    
    namespace xk_System.HotUpdate
    {
        public class AssetBundleHotUpdateManager : Singleton<AssetBundleHotUpdateManager>
        {
            private int mStreamFolderVersionId=-1;
            private int mExternalStoreVersionId=-1;
            private int mWebServerVersionId=-1;
    
            private List<AssetBundleInfo> mExternalStoreABInfoList = new List<AssetBundleInfo>();
            private List<AssetBundleInfo> mWebServerABInfoList = new List<AssetBundleInfo>();
            private List<AssetBundleInfo> mStreamFolderABInfoList = new List<AssetBundleInfo>();
    
            private DownLoadAssetInfo mDownLoadAssetInfo = new DownLoadAssetInfo();
    
            public LoadProgressInfo mTask = new LoadProgressInfo();
    
            public IEnumerator CheckUpdate()
            {
                mTask.progress = 0;
                mTask.Des = "正在检查资源";
                yield return CheckVersionConfig();
                if (mDownLoadAssetInfo.mAssetNameList.Count > 0)
                {
                    mTask.progress += 10;
                    mTask.Des = "正在下载资源";
                    yield return DownLoadAllNeedUpdateBundle();
                }
                else
                {
                    mTask.progress = 100;
                }
            }
    
            /// <summary>
            /// 检查版本配置文件
            /// </summary>
            /// <returns></returns>
            private IEnumerator CheckVersionConfig()
            {
                yield return InitLoadExternalStoreVersionConfig();
                yield return InitLoadStreamFolderVersionConfig();
                yield return InitLoadWebServerVersionConfig();
    
                DebugSystem.Log("本地版本号:" + mExternalStoreVersionId);
                DebugSystem.Log("WebServer版本号:" + mWebServerVersionId);
                DebugSystem.Log("StreamFolder版本号:" + mStreamFolderVersionId);
                if (mWebServerVersionId > mExternalStoreVersionId)
                {
                    yield return InitLoadExternalStoreABConfig();
                    if (mWebServerVersionId > mStreamFolderVersionId)
                    {
                        yield return InitLoadWebServerABConfig();
                        CheckAssetInfo(AssetBundlePath.Instance.WebServerPathUrl, mWebServerABInfoList);
                    }
                    else
                    {
                        yield return InitLoadStreamFolderABConfig();
                        CheckAssetInfo(AssetBundlePath.Instance.StreamingAssetPathUrl, mStreamFolderABInfoList);
                    }
                }
                else if (mStreamFolderVersionId > mExternalStoreVersionId)
                {
                    yield return InitLoadExternalStoreABConfig();
                    yield return InitLoadStreamFolderABConfig();
                    CheckAssetInfo(AssetBundlePath.Instance.StreamingAssetPathUrl, mStreamFolderABInfoList);
                }
            }
    
            /// <summary>
            /// 检查资源配置文件
            /// </summary>
            /// <returns></returns>
            private void CheckAssetInfo(string url, List<AssetBundleInfo> mUpdateABInfoList)
            {
                mDownLoadAssetInfo.url = url;
                foreach (AssetBundleInfo k in mUpdateABInfoList)
                {
                    AssetBundleInfo mBundleInfo = mExternalStoreABInfoList.Find((x) =>
                    {
                        if (x.mHash.isValid && k.mHash.isValid)
                        {
                            return x.mHash.Equals(k.mHash);
                        }
                        else
                        {
                            DebugSystem.LogError("Hash is no Valid");
                            return false;
                        }
                    });
                    if (mBundleInfo == null)
                    {
                        mDownLoadAssetInfo.mAssetNameList.Add(k.bundleName);
                    }
                }
                if (mDownLoadAssetInfo.mAssetNameList.Count > 0)
                {
                    mDownLoadAssetInfo.mAssetNameList.Add(AssetBundlePath.AssetDependentFileBundleName);
                }
                DebugSystem.Log("需要下载更新的个数:" + mDownLoadAssetInfo.mAssetNameList.Count);
            }
    
            private IEnumerator InitLoadWebServerVersionConfig()
            {
                string url = AssetBundlePath.Instance.WebServerPathUrl + "/" + AssetBundlePath.versionConfigBundleName;
                WWW www = new WWW(url);
                yield return www;
                if (www.isDone)
                {
                    if (!string.IsNullOrEmpty(www.error))
                    {
                        DebugSystem.LogError("www Load Error:" + www.error);
                        www.Dispose();
                        yield break;
                    }
                }
    
                AssetBundle mConfigBundle = www.assetBundle;
                TextAsset mVersionConfig = mConfigBundle.LoadAsset<TextAsset>(AssetBundlePath.versionConfigAssetName);
                mWebServerVersionId = ParseXML(mVersionConfig);
                mConfigBundle.Unload(false);
                www.Dispose();
            }
    
            private IEnumerator InitLoadExternalStoreVersionConfig()
            {
                string url = AssetBundlePath.Instance.ExternalStorePathUrl + "/" + AssetBundlePath.versionConfigBundleName;
                WWW www = new WWW(url);
                yield return www;
                if (www.isDone)
                {
                    if (!string.IsNullOrEmpty(www.error))
                    {
                        DebugSystem.LogError("www Load Error:" + www.error);
                        www.Dispose();
                        yield break;
                    }
                }
                AssetBundle mConfigBundle = www.assetBundle;
                TextAsset mVersionConfig = mConfigBundle.LoadAsset<TextAsset>(AssetBundlePath.versionConfigAssetName);
                mExternalStoreVersionId = ParseXML(mVersionConfig);
                mConfigBundle.Unload(false);
                www.Dispose();
            }
    
            private IEnumerator InitLoadStreamFolderVersionConfig()
            {
                string url = AssetBundlePath.Instance.StreamingAssetPathUrl + "/" + AssetBundlePath.versionConfigBundleName;
                WWW www = new WWW(url);
                yield return www;
                if (www.isDone)
                {
                    if (!string.IsNullOrEmpty(www.error))
                    {
                        DebugSystem.LogError("www Load Error:" + www.error);
                        www.Dispose();
                        yield break;
                    }
                }
                AssetBundle mConfigBundle = www.assetBundle;
                TextAsset mVersionConfig = mConfigBundle.LoadAsset<TextAsset>(AssetBundlePath.versionConfigAssetName);
                mStreamFolderVersionId = ParseXML(mVersionConfig);
                mConfigBundle.Unload(false);
                www.Dispose();
            }
    
            private IEnumerator InitLoadWebServerABConfig()
            {
                string url = AssetBundlePath.Instance.WebServerPathUrl + "/" + AssetBundlePath.AssetDependentFileBundleName;
                WWW www = new WWW(url);
                yield return www;
                if (www.isDone)
                {
                    if (!string.IsNullOrEmpty(www.error))
                    {
                        DebugSystem.LogError("www Load Error:" + www.error);
                        www.Dispose();
                        yield break;
                    }
                }
                AssetBundle mConfigBundle = www.assetBundle;
                AssetBundleManifest mAllBundleMainifest = mConfigBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
                if (mAllBundleMainifest == null)
                {
                    DebugSystem.LogError("Mainifest is Null");
                    www.Dispose();
                    yield break;
                }
                string[] mAssetNames = mAllBundleMainifest.GetAllAssetBundles();
                if (mAssetNames != null)
                {
                    foreach (var v in mAssetNames)
                    {
                        string bundleName = v;
                        string[] bundleDependentList = mAllBundleMainifest.GetAllDependencies(v);
                        Hash128 mHash = mAllBundleMainifest.GetAssetBundleHash(v);
                        AssetBundleInfo mABInfo = new AssetBundleInfo(bundleName, mHash, bundleDependentList);
                        mWebServerABInfoList.Add(mABInfo);
                    }
                }
                else
                {
                    DebugSystem.Log("初始化资源依赖文件: Null");
                }
                mConfigBundle.Unload(false);
                www.Dispose();
            }
    
            private IEnumerator InitLoadExternalStoreABConfig()
            {
                string url = AssetBundlePath.Instance.ExternalStorePathUrl + "/" + AssetBundlePath.AssetDependentFileBundleName;
                WWW www = new WWW(url);
                yield return www;
                if (www.isDone)
                {
                    if (!string.IsNullOrEmpty(www.error))
                    {
                        DebugSystem.LogError("www Load Error:" + www.error);
                        www.Dispose();
                        yield break;
                    }
                }
                AssetBundle mConfigBundle = www.assetBundle;
                AssetBundleManifest mAllBundleMainifest = mConfigBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
                if (mAllBundleMainifest == null)
                {
                    DebugSystem.LogError("Mainifest is Null");
                    www.Dispose();
                    yield break;
                }
                string[] mAssetNames = mAllBundleMainifest.GetAllAssetBundles();
                if (mAssetNames != null)
                {
                    foreach (var v in mAssetNames)
                    {
                        string bundleName = v;
                        string[] bundleDependentList = mAllBundleMainifest.GetAllDependencies(v);
                        Hash128 mHash = mAllBundleMainifest.GetAssetBundleHash(v);
                        AssetBundleInfo mABInfo = new AssetBundleInfo(bundleName, mHash, bundleDependentList);
                        mExternalStoreABInfoList.Add(mABInfo);
                    }
                }
                else
                {
                    DebugSystem.Log("初始化资源依赖文件: Null");
                }
                mConfigBundle.Unload(false);
                www.Dispose();
            }
    
            private IEnumerator InitLoadStreamFolderABConfig()
            {
                string url = AssetBundlePath.Instance.StreamingAssetPathUrl + "/" + AssetBundlePath.AssetDependentFileBundleName;
                WWW www = new WWW(url);
                yield return www;
                if (www.isDone)
                {
                    if (!string.IsNullOrEmpty(www.error))
                    {
                        DebugSystem.LogError("www Load Error:" + www.error);
                        www.Dispose();
                        yield break;
                    }
                }
                AssetBundle mConfigBundle = www.assetBundle;
                AssetBundleManifest mAllBundleMainifest = mConfigBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
                if (mAllBundleMainifest == null)
                {
                    DebugSystem.LogError("Mainifest is Null");
                    www.Dispose();
                    yield break;
                }
                string[] mAssetNames = mAllBundleMainifest.GetAllAssetBundles();
                if (mAssetNames != null)
                {
                    foreach (var v in mAssetNames)
                    {
                        string bundleName = v;
                        string[] bundleDependentList = mAllBundleMainifest.GetAllDependencies(v);
                        Hash128 mHash = mAllBundleMainifest.GetAssetBundleHash(v);
                        AssetBundleInfo mABInfo = new AssetBundleInfo(bundleName, mHash, bundleDependentList);
                        mStreamFolderABInfoList.Add(mABInfo);
                    }
                }
                else
                {
                    DebugSystem.Log("初始化资源依赖文件: Null");
                }
                mConfigBundle.Unload(false);
                www.Dispose();
            }
    
            /// <summary>
            /// 得到版本号
            /// </summary>
            /// <param name="mbytes"></param>
            /// <returns></returns>
            public int ParseXML(TextAsset mTextAsset)
            {
                XmlDocument mdoc = new XmlDocument();
                mdoc.LoadXml(mTextAsset.text);
                foreach (XmlNode v in mdoc.ChildNodes)
                {
                    if (v.Name == "root")
                    {
                        foreach (XmlNode x in v.ChildNodes)
                        {
                            if (x.Name.Contains("versionId"))
                            {
                                return int.Parse(x.InnerText);
                            }
                        }
                    }
                }
                return 0;
            }
    
            private IEnumerator DownLoadAllNeedUpdateBundle()
            {
                List<string> bundleList = mDownLoadAssetInfo.mAssetNameList;
                List<string>.Enumerator mIter = bundleList.GetEnumerator();
    
                uint addPro = (uint)Mathf.CeilToInt((LoadProgressInfo.MaxProgress - mTask.progress)/(float)bundleList.Count);
                while (mIter.MoveNext())
                {
                    DebugSystem.LogError("下载的文件:" + mDownLoadAssetInfo.url + " | " + mIter.Current);
                    yield return DownLoadSingleBundle(mDownLoadAssetInfo.url, mIter.Current);
                    mTask.progress+=addPro;
                }
            }
    
            private IEnumerator DownLoadSingleBundle(string path, string bundleName)
            {
                string url = path + "/" + bundleName;
                WWW www = new WWW(url);
                yield return www;
                if (www.isDone)
                {
                    if (!string.IsNullOrEmpty(www.error))
                    {
                        DebugSystem.LogError("www Load Error:" + www.error);
                        www.Dispose();
                        yield break;
                    }
                }
                string savePath = AssetBundlePath.Instance.ExternalStorePath + "/" + bundleName;
                SaveDownLoadedFile(savePath, www.bytes);
                www.Dispose();
            }
    
            private void SaveDownLoadedFile(string path, byte[] mdata)
            {
                if (File.Exists(path))
                {
                    File.Delete(path);
                }
                FileInfo mFileInfo = new FileInfo(path);
                FileStream mFileStream = mFileInfo.OpenWrite();
                mFileStream.Write(mdata, 0, mdata.Length);
                mFileStream.Flush();
                mFileStream.Close();
            }
    
            private class DownLoadAssetInfo
            {
                public string url;
                public List<string> mAssetNameList = new List<string>();
            }
    
    
        }
    }

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

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

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

    2:加载程序集,代码如下
    using UnityEngine;
    using System.Collections;
    using System.Reflection;
    using xk_System.Debug;
    using System;
    
    namespace xk_System.AssetPackage
    {
        public class AssemblyManager : Singleton<AssemblyManager>
        {
            private Assembly mHotUpdateAssembly;
            private Assembly mCurrentAssembly;
            /// <summary>
            /// 加载程序集
            /// </summary>
            /// <returns></returns>
            public IEnumerator LoadAssembly()
            {
                AssetInfo mAssetInfo = ResourceABsFolder.Instance.scripts.mtest;
                string path = AssetBundlePath.Instance.ExternalStorePathUrl;
    
                string bundleName1 = mAssetInfo.bundleName;
                string url = path + "/" + bundleName1;
                WWW www = new WWW(url);
                yield return www;
                if (www.isDone)
                {
                    if (!string.IsNullOrEmpty(www.error))
                    {
                        DebugSystem.LogError("www Load Error:" + www.error);
                        yield break;
                    }
                }
                AssetBundle mConfigBundle = www.assetBundle;
                TextAsset mAsset = mConfigBundle.LoadAsset<TextAsset>(mAssetInfo.assetName);
                mHotUpdateAssembly = Assembly.Load(mAsset.bytes);
                if (mHotUpdateAssembly != null)
                {
                    DebugSystem.Log("加载程序集:" + mHotUpdateAssembly.FullName);
                }
                else
                {
                    DebugSystem.Log("加载程序集: null");
                }
                mCurrentAssembly = this.GetType().Assembly;
                DebugSystem.Log("当前程序集:" + mCurrentAssembly.FullName);
                if (mCurrentAssembly.FullName.Equals(mHotUpdateAssembly.FullName))
                {
                    DebugSystem.LogError("加载程序集名字有误");
                }
                mConfigBundle.Unload(false);
            }
    
            public object CreateInstance(string typeFullName)
            {
                if (mHotUpdateAssembly != null)
                {
                    return mHotUpdateAssembly.CreateInstance(typeFullName);
                }
                else
                {
                   return mCurrentAssembly.CreateInstance(typeFullName);
                }
            }
    
            /// <summary>
            /// 仅仅写入口时,调用。(否则,会使程序变得混乱,反正我是搞乱了)
            /// </summary>
            /// <param name="obj"></param>
            /// <param name="typeFullName"></param>
            /// <returns></returns>
            public Component AddComponent(GameObject obj, string typeFullName)
            {
                DebugSystem.Log("Type: " + typeFullName);
                if (mHotUpdateAssembly != null)
                {
                    Type mType = mHotUpdateAssembly.GetType(typeFullName);
                    return obj.AddComponent(mType);
                }
                else
                {
                    Type mType = typeFullName.GetType();
                    return obj.AddComponent(mType);
                }
            }
        }
    }

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

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

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    展开全文
  • Unity3D资源管理架构

    2019-08-10 21:40:39
    转载自Unity3D资源管理架构Unity3D引擎中,场景资源文件(.unity)是以2进制格式存储的,但同时它也有一种基于文本的表现格式。可在Edit>Project Setting>Editor 中设置: 1.使用binary2text.exe(win下目录...

    转载自Unity3D资源管理架构

    在Unity3D引擎中,场景资源文件(.unity)是以2进制格式存储的,但同时它也有一种基于文本的表现格式。可在Edit>Project Setting>Editor 中设置:
    在这里插入图片描述

    1.使用binary2text.exe(win下目录:Editor\Data\Tools)可将.unity文件转换成.txt文件,只需将.unity文件拖拽到binary2text.exe上即可生成.txt;

    在这里插入图片描述

    2.Bin2Text.unity为测试场景场景中只有一个名为“sakyaer”的空物体;
    在这里插入图片描述
    3.对应这样一个场景,它的文本格式使用YAML格式存储,信息表如下:

    • 其中ClassID是Unity3D中类的序列编号,如:GameObject类ClassID=1,具体类的ID参照官方网
    • http://docs.unity3d.com/Manual/ClassIDReference.html
    • ID项为随记分配给每个实例的唯一标识
    • 资源文件使用m_作为前缀
    • 其中m_GameObject (file 0 path 1163297905)表现transform对gameobject的从属关系
    External References
    
    
    ID: 1 (ClassID: 29) SceneSettings
        m_ObjectHideFlags 0 (unsigned int)
        m_PVSData  (vector)
            size 0 (int)
    
        m_PVSObjectsArray  (vector)
            size 0 (int)
    
        m_PVSPortalsArray  (vector)
            size 0 (int)
    
        m_OcclusionBakeSettings  (OcclusionBakeSettings)
            smallestOccluder 5 (float)
            smallestHole 0.25 (float)
            backfaceThreshold 100 (float)
    
    
    ID: 2 (ClassID: 104) RenderSettings
        m_Fog 0 (bool)
        m_FogColor (0.5 0.5 0.5 1) (ColorRGBA)
        m_FogMode 3 (int)
        m_FogDensity 0.01 (float)
        m_LinearFogStart 0 (float)
        m_LinearFogEnd 300 (float)
        m_AmbientLight (0.2 0.2 0.2 1) (ColorRGBA)
        m_SkyboxMaterial (file 0 path 0) (PPtr<Material>)
        m_HaloStrength 0.5 (float)
        m_FlareStrength 1 (float)
        m_FlareFadeSpeed 3 (float)
        m_HaloTexture (file 0 path 0) (PPtr<Texture2D>)
        m_SpotCookie (file 0 path 0) (PPtr<Texture2D>)
        m_ObjectHideFlags 0 (unsigned int)
    
    
    ID: 3 (ClassID: 127) LevelGameManager
        m_ObjectHideFlags 0 (unsigned int)
    
    
    ID: 4 (ClassID: 157) LightmapSettings
        m_ObjectHideFlags 0 (unsigned int)
        m_LightProbes (file 0 path 0) (PPtr<LightProbes>)
        m_Lightmaps  (vector)
            size 0 (int)
    
        m_LightmapsMode 1 (int)
        m_BakedColorSpace 0 (int)
        m_UseDualLightmapsInForward 0 (bool)
        m_LightmapEditorSettings  (LightmapEditorSettings)
            m_Resolution 50 (float)
            m_LastUsedResolution 0 (float)
            m_TextureWidth 1024 (int)
            m_TextureHeight 1024 (int)
            m_BounceBoost 1 (float)
            m_BounceIntensity 1 (float)
            m_SkyLightColor (0.86 0.93 1 1) (ColorRGBA)
            m_SkyLightIntensity 0 (float)
            m_Quality 0 (int)
            m_Bounces 1 (int)
            m_FinalGatherRays 1000 (int)
            m_FinalGatherContrastThreshold 0.05 (float)
            m_FinalGatherGradientThreshold 0 (float)
            m_FinalGatherInterpolationPoints 15 (int)
            m_AOAmount 0 (float)
            m_AOMaxDistance 0.1 (float)
            m_AOContrast 1 (float)
            m_LODSurfaceMappingDistance 1 (float)
            m_Padding 0 (int)
            m_TextureCompression 0 (bool)
            m_LockAtlas 0 (bool)
    
    
    ID: 5 (ClassID: 196) NavMeshSettings
        m_ObjectHideFlags 0 (unsigned int)
        m_BuildSettings  (NavMeshBuildSettings)
            agentRadius 0.5 (float)
            agentHeight 2 (float)
            agentSlope 45 (float)
            agentClimb 0.4 (float)
            ledgeDropHeight 0 (float)
            maxJumpAcrossDistance 0 (float)
            accuratePlacement 0 (bool)
            minRegionArea 2 (float)
            widthInaccuracy 16.6667 (float)
            heightInaccuracy 10 (float)
        m_NavMesh (file 0 path 0) (PPtr<NavMesh>)
    
    
    ID: 1163297905 (ClassID: 1) GameObject
        m_ObjectHideFlags 0 (unsigned int)
        m_PrefabParentObject (file 0 path 0) (PPtr<EditorExtension>)
        m_PrefabInternal (file 0 path 0) (PPtr<Prefab>)
        m_Component  (vector)
            size 1 (int)
            data  (pair)
                first 4 (int)
                second (file 0 path 1163297906) (PPtr<Component>)
    
        m_Layer 0 (unsigned int)
        m_Name "Sakyaer" (string)
        m_TagString "Untagged" (string)
        m_Icon (file 0 path 0) (PPtr<Texture2D>)
        m_NavMeshLayer 0 (unsigned int)
        m_StaticEditorFlags 0 (unsigned int)
        m_IsActive 1 (bool)
    
    
    ID: 1163297906 (ClassID: 4) Transform
        m_ObjectHideFlags 0 (unsigned int)
        m_PrefabParentObject (file 0 path 0) (PPtr<EditorExtension>)
        m_PrefabInternal (file 0 path 0) (PPtr<Prefab>)
        m_GameObject (file 0 path 1163297905) (PPtr<GameObject>)
        m_LocalRotation  (Quaternionf)
            x 0 (float)
            y 0 (float)
            z 0 (float)
            w 1 (float)
        m_LocalPosition (0 0 0) (Vector3f)
        m_LocalScale (1 1 1) (Vector3f)
        m_Children  (vector)
            size 0 (int)
    
        m_Father (file 0 path 0) (PPtr<Transform>)
        m_RootOrder 0 (int)
    
    

    4.Unity3D中对于每一个资源文件都会生成对应.meta文件,该文件可以用记事本直接打开;

    guid(全局唯一标识符,Globally Unique Identifier)是系统随机生成的对资源的标识符,guid在游戏运行时会被用来生成一个hashid;

    而根据guid的前两位0a可以在工程Library目录下metadate(元数据)0a目录下找到,对应的二进制文件,该文件可以使用binary2text.exe打开,得到的txt文件,记录了.meta文件对应资源的所有详细信息.

    guid: 0a4a878577c88654795d8c6aee74368d

    展开全文
  • Unity手游框架资源管理

    千次阅读 2017-02-17 09:51:08
    Unity手游框架资源管理引子资源管理是做什么用的,让我们先来看一段代码public void SetHeroInfo(HeroInfo heroInfo) { GetControls(); int heroResId = heroInfo.Id & 0xffff; HeroTableData heroTableData =...
  • Unity资源管理和策略

    2021-02-02 01:51:21
    Unity资源管理 常用路径 Unity移动端开发中常常会用到四种路径。 AssetDatabse 在Editor环境下,Unity提供了一个AssetDatabase类,提供了各种各样的资源加载、管理等方法。 热更新 AB包加载 资源加载
  • Unity3D资源管理——资源管理框架

    千次阅读 2018-09-17 21:15:03
    使用Unity2017.3.1f 1.2 dll (1)EPPlus (2)Excel (3)ICSharpCode.SharpZipLi (4)System.Data(是mono文件夹底下的dll)   2.需求 1.将Excel配置文件转化成对应的数据代码 2.将Excel文件转化成...
  • Unity资源管理(二)-Resources文件夹 强烈不建议使用Resources系统,原因如下: 使用Resources文件夹将会使细粒度的内存管理变得更难 对Resources文件夹的不恰当使用会导致应用程序构架和启动时间变长 随着...
  • 2.资源管理是如何做的,如何更新与打空包? 3.资源管理的平台,版本,渠道是如何管理的? 4.项目框架是如何让美术,策划,程序愉快的工作的? 5.真机调试,看打印日志你是如何处理的? 6.Unity如何避免多人提交...
  • 如果想要了解AssetBundle相关,资源管理器实现的逻辑的话,可以先看一下这篇:【AssetBundle】Unity AssetBundle打包和资源加载解析。 项目 Demo.unitypackage 效果:运行时加载资源 使用说明 Entrance脚本是入口...
  • Unity 资源映射框架

    2021-04-06 22:31:21
    于是我们可以在编辑器中生成一个资源映射表,使程序运行时可以通过文件的名字直接取得文件的目录。 本文以 prefab 的资源映射表为例??????????????????????????????????????...
  • Unity3d资源管理分析

    2017-06-26 22:48:50
    转自:Unity3d资源管理分析 基本信息 美术资源应导出为AssetBundle文件。这种AssetBundle有两种存储方式:可以是未压缩的,也可以使用7z算法压缩,默认压缩。以我手头的一个蒙皮动画角色为例,压缩后文件大小由...
  • 1.资源加载监听者接口using UnityEngine; using System.Collections;/// /// 资源加载回调 /// public interface IResLoadListener { void Finished(object asset); void Failed();} 2.资源信息类using Uni
  • Unity】 HTFramework框架(十)Resource资源管理

    千次阅读 热门讨论 2019-03-27 18:59:21
    索引Resource资源管理器简介使用Resource资源管理器设置资源加载模式加载通用资源加载预制体卸载资源 Resource资源管理器简介 Resource资源管理器主要用于动态加载资源(只支持异步加载),现在主要支持Resource...
  • 这里写下关于Unity3D对于内存的管理与优化.  Unity3D 里有两种动态加载机制:一个是Resources.Load,另外一个通过AssetBundle,其实两者区别不大。 Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载...
  • 这篇只涉及基础原理,下篇会讲如何实现一个简单的资源管理框架。 一、Assets和Objects 资源(Asset)是存储在Unity项目的Assets文件夹中的磁盘文件。有些资源的数据格式是Unity原声支持的,有些资源则需要转换为源生...
  • Unity GameFramework加载资源流程: 加载资源(LoadAsset) 检查资源(CheckAsset) AssetInfo是资源信息,ResourceInfo是资源对应的AB包信息,在单机包初始化资源或热更包下载前检查资源时,会根据本地的...
  • Unity GameFramework提供一套完整的asset bundle编辑、构建、分析工具,以及资源加载、使用、销毁等处理。 工具主要分为 AssetBundleEditor:ab包编辑 AssetBundleBuilder:ab包构建 AssetBundleAnalyzer:ab...
  • Unity3d 资源管理

    2017-07-31 09:04:44
    这里写下关于Unity3D对于内存的管理与优化.  Unity3D 里有两种动态加载机制:一个是Resources.Load,另外一个通过AssetBundle,其实两者区别不大。 Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载...
  • 更新日期:2020年8月13日。 Github源码:[点我获取源码] ...AssetsMaster(资产的主人)允许你在编辑模式或是运行模式非常直观的查看和管理当前打开场景中的你感兴趣的资产,目前可以管理如下四种资产:材质,贴图.
  • 编辑资源和AssetBundle 大致流程: 加载AssetBundleEditor.xml 根据配置的路径和筛选条件,选出满足条件的文件、抽象成SourceFolder、SourceAsset类,用于显示在编辑器的右侧列表:待加入ab的资源 这里筛选...
  • 将AssetBundleEditor编辑的资源和ab生成各平台、各类型(单机、热更、Packed)的ab包 压缩方式 BuildAssetBundleOptions.None:默认压缩方式,LZMA压缩格式,压缩后最小,解压时间较长,使用前需要先解压 ,使用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,909
精华内容 2,763
关键字:

unity资源管理框架