UnityAsetBundle开发模式管理

公司终于使用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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值