UnityAsetBundle开发模式管理

来源:互联网 发布:搞笑照片软件 编辑:程序博客网 时间:2024/06/10 03:39

公司终于使用AssetBundle来开发游戏了。虽然AssetBunle对项目的资源更新方面起到了很大的便利。但是在开发过程中却多有不变。主要体现在一下几个方面。
1:资源加载过程,直接使用资源,本地bundle资源,网上bundle资源这三种模式切换很麻烦。
2:加载具体资源,需要传入相应的资源字符串,字符拼写容易出错。
针对以上两种问题,我想出以下的解决方案。
1:无论是,本地资源,本地bundle资源,网上bundle资源,都使用同一套接口来调用。模式之间的切换,通过预先指定就行了。
2:加载本地资源时,资源并没有在resource下,因此主要用于编辑器模式,所以通过配置相关的路径信息来加载资源,我获取了所有的bundle资源的路径,并以json表来保存。
3:针对设置的bundle,相应的bundle资源,通过生成相应的枚举,和类变量,通过引用。就可以避免字符串之间的传入错误。
下面是相关的代码,可以参考:
1:配置bundle资源的路径信息
2:生成所有bundle资源的枚举
3:以bundle名+“_”+”prefab”为类名,生成类名,资源名用字段保存,用const来修饰

[MenuItem("LazerSelect/Bundle/Config")]        private static void BundlePathConfig()        {            //准备一个代码编译器单元            CodeCompileUnit unit = new CodeCompileUnit();            //准备必要的命名空间(这个是指要生成的类的空间)            CodeNamespace sampleNamespace = new CodeNamespace();            CodeTypeDeclaration bundleEnum = new CodeTypeDeclaration("EBundleName");            bundleEnum.IsEnum = true;            bundleEnum.TypeAttributes = TypeAttributes.Public;            sampleNamespace.Types.Add(bundleEnum);            unit.Namespaces.Add(sampleNamespace);            CodeMemberField field;            CodeTypeDeclaration bundleClass;            int bundleIndex = 0;            Dictionary<string, PrefabPath> prefabDict = new Dictionary<string, PrefabPath>();            string[] assetBundleNames = AssetDatabase.GetAllAssetBundleNames();            Dictionary<ObjPoolItem, string> pool_item_bundle_dict = new Dictionary<ObjPoolItem, string>();            foreach (string bundleName in assetBundleNames)            {                Debug.Log("bundle name:" + bundleName);                field = new CodeMemberField(typeof(System.Enum), bundleName);                field.InitExpression = new CodePrimitiveExpression(bundleIndex);                bundleEnum.Members.Add(field);                ++bundleIndex;                bundleClass = new CodeTypeDeclaration(string.Format("{0}_Prefab", bundleName));                bundleClass.IsClass = true;                bundleClass.TypeAttributes = TypeAttributes.Public;                sampleNamespace.Types.Add(bundleClass);                PrefabPath prefabPathInfo = new PrefabPath();                prefabPathInfo.PrefabPathDict = new Dictionary<string, string>();                string[] prefabPaths = AssetDatabase.GetAssetPathsFromAssetBundle(bundleName);                foreach (string prefabPath in prefabPaths)                {                    if (prefabPath.Contains(".mat")) { continue;}                    if (Helper.IsChinaString(prefabPath)){continue;}                    if (prefabPath.Contains(".prefab"))                    {                        ObjPoolItem poolItem = (UnityEditor.AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)) as GameObject).GetComponent<ObjPoolItem>();                        if (poolItem)                        {                            pool_item_bundle_dict[poolItem] = bundleName;                        }                    }                    string[] splitStrings = prefabPath.Split('/', '.');                    string prefabName = splitStrings[splitStrings.Length - 2];                    Debug.Log("prefabPath:" + prefabPath + " prefabname:" + prefabName);                    int prefabIndex;                    if (int.TryParse(prefabName, out prefabIndex))                    {                        continue;                    }                    if (prefabName.Contains("-"))                    {                        continue;                    }                    if (!prefabPathInfo.PrefabPathDict.ContainsKey(prefabName))                    {                        field = new CodeMemberField(typeof(String), prefabName);                        field.Attributes = MemberAttributes.Public | MemberAttributes.Const;                        field.InitExpression = new CodePrimitiveExpression(prefabName);                        bundleClass.Members.Add(field);                        prefabPathInfo.PrefabPathDict[prefabName] = prefabPath;                    }                    else                    {                        if (prefabPath.Contains(".prefab"))//优先保存预设                        {                            prefabPathInfo.PrefabPathDict[prefabName] = prefabPath;                        }                    }                }                prefabDict[bundleName] = prefabPathInfo;            }            string json = JsonConvert.SerializeObject(prefabDict, Newtonsoft.Json.Formatting.Indented);//JsonMapper.ToJson(prefabDict);            Debug.Log(json);            byte[] bytes = System.Text.UTF8Encoding.UTF8.GetBytes(json);            File.WriteAllBytes(Application.dataPath + "/" + "Project_Fish/BundleBuilder/BundleConfigJson/BundleConfig.json", bytes);            string outputFile = Application.dataPath + "/" + "Project_Fish/BundleBuilder/BundleConfigJson/BundleConfig.cs";// "Customer.cs";            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");            CodeGeneratorOptions options = new CodeGeneratorOptions();            options.BracingStyle = "C";            options.BlankLinesBetweenMembers = false;            using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputFile))            {                provider.GenerateCodeFromCompileUnit(unit, sw, options);            }            AssetDatabase.Refresh();            foreach (KeyValuePair<ObjPoolItem, string> key_value in pool_item_bundle_dict)            {                Debug.Log(key_value.Value);                //标记预设为修改状态 这步很重要,不执行这步操作。关闭Unity后。预设并不会保存。                EditorUtility.SetDirty(key_value.Key.gameObject);                //key_value.Key.Bundle = key_value.Value;// (EBundleName)Enum.Parse(typeof(EBundleName), key_value.Value);                key_value.Key.BundleName = (EBundleName)Enum.Parse(typeof(EBundleName), key_value.Value);            }            AssetDatabase.Refresh();            AssetDatabase.SaveAssets();            pool_item_bundle_dict = null;            GC.Collect();        }

1:此文件,是三种资源加载的通用接口
2:如果是编辑器模式,先加载本地资源路径信息json表(上面代码生成的)
3:如果是本地bundle模式,需要生成相关的bundle,保存在streamassets文件夹localbundle下
4:如果是服务器bundle模式,保证在调用相关的接口调用之前,将下载的bundle保存在字典即可。

public class BundleResourceManager :CommonSingleton<BundleResourceManager>{    //bundle 字典    public Dictionary<string, AssetBundle> AssetBundlePool = new Dictionary<string, AssetBundle>();    //资源字典    public Dictionary<string, PrefabPath> ResourceDict;    public override void Initialize()    {        if(AppConst.BundleType == EBundleType.NoBundle)        {#if UNITY_EDITOR            ResourceDict = JsonMapper.ToObject<Dictionary<string,PrefabPath>>((UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Project_Fish/BundleBuilder/BundleConfigJson/BundleConfig.json", typeof(TextAsset)) as TextAsset).text);            //SDebug.Log(ResourceDict.Count);#endif        }        else if(AppConst.BundleType == EBundleType.LocalBundle)        {            GetBundle(EBundleName.fishuiatlas);// typeof(EBundleName),"fishuiatlas"));            GetBundle(EBundleName.fishingameuiatlas);// (EBundleName)Enum.Parse(typeof(EBundleName), "fishingameuiatlas"));            GetBundle(EBundleName.common); //(EBundleName)Enum.Parse(typeof(EBundleName), "common"));        }    }    public T CreateObj<T>(EBundleName bundleName,string prefabName) where T :Object    {        SDebug.Log("need create bundle:"+bundleName+"   prefab name:"+prefabName);        if(prefabName.Contains("."))//去除后缀        {            prefabName = prefabName.Split('.')[0];        }        return CreateObj(bundleName, prefabName,typeof(T)) as T;    }    public Object CreateObj(EBundleName bundleName, string prefabName)    {        return CreateObj(bundleName, prefabName, typeof(GameObject));    }    //实例化预设    public UnityEngine.Object CreateObj(EBundleName bundleName, string prefabName,Type type)    {        SDebug.Log("need create bundle:" + bundleName + "   prefab name:" + prefabName);        if (AppConst.BundleType == EBundleType.NoBundle)        {            string prefabPath = ResourceDict[bundleName.ToString()].PrefabPathDict[prefabName];            SDebug.Log("path:" + prefabPath);#if UNITY_EDITOR            return UnityEditor.AssetDatabase.LoadAssetAtPath(prefabPath, type);#endif            return null;        }        else if (AppConst.BundleType == EBundleType.LocalBundle)        {            AssetBundle assetBundle;            if (AssetBundlePool.TryGetValue(bundleName.ToString(), out assetBundle))            {                return assetBundle.LoadAsset(prefabName);            }            assetBundle = GetBundle(bundleName);            if (assetBundle != null)            {                return assetBundle.LoadAsset(prefabName);            }            Debug.LogError("the prefab name:" + prefabName + " is not exist!");            return null;        }        else        {            AssetBundle assetBundle;            if (AssetBundlePool.TryGetValue(bundleName.ToString(), out assetBundle))            {                return assetBundle.LoadAsset(prefabName);            }            Debug.LogError("the prefab name:" + prefabName + " is not exist!");            return null;        }    }    public void SetBundle(string bundleName,AssetBundle bundle)    {        AssetBundlePool[bundleName] = bundle;    }    public AssetBundle GetBundle(EBundleName bundleName)    {        AssetBundle result;        if(AssetBundlePool.TryGetValue(bundleName.ToString(),out result))        {            return result;        }        if(AppConst.BundleType == EBundleType.LocalBundle)        {            result = AssetBundle.LoadFromFile(string.Format("{0}/{1}", Util.LocalBundlePath, bundleName));            SetBundle(bundleName.ToString(), result);            return result;        }        Debug.LogError(string.Format("the bundle name :{0} is not exist!", bundleName));        return null;    }}
原创粉丝点击