使用UnityEditor制作可视化打包AssetBundle(一)

Unity版本:Unity 5.6.6f2

基本流程

  • 创建xml文件,将xml内容解析到实体类中
  • 绘制UnityEditor窗口,将xml内容绘制到窗口中
  • 打包AssetBundle
  • 加载AssetBundle(异步和同步)

准备原材料:xml和entity实体类




  
    
      
    
    
      
    
  
// AssetBundleEntity.cs
using System.Collections.Generic;

public class AssetBundleEntity
{
    /// 
    /// 打包指定专用Key(唯一性)
    /// 
    public string Key;

    /// 
    /// 名称
    /// 
    public string Name;

    /// 
    /// 标记
    /// 
    public string Tag;

    /// 
    /// 版本号
    /// 
    public int Version;

    /// 
    /// 大小(K)
    /// 
    public long Size;

    /// 
    /// 将要存放的文件夹
    /// 
    public string ToPath;

    /// 
    /// 资源存放路径集合
    /// 
    private List m_PathList = new List();

    public List PathList
    {
        get
        {
            return m_PathList;
        }
    }
}

PathList: 后面会使用到这个属性,通过这个属性将所有资源打包Assetbundle,保存在自己定义的路径/ToPath/下

XML读取类的编写

// AssetBundleDAL.cs
using System.Collections.Generic;
using System.Xml.Linq; 

public class AssetBundleDAL
{
    /// 
    /// xml路径
    /// 
    private string m_XMLPath;

    /// 
    /// 返回的AssetBundle实体集合
    /// 
    private List m_List = null;

    public AssetBundleDAL(string xmlPath)
    {
        this.m_XMLPath = xmlPath;
        m_List = new List();
    }

    #region 读取xml文件 GetList
    /// 
    /// 读取xml文件  存储到实体集合中
    ///  
    public List GetList()
    {
        m_List.Clear();

        //读取xml  把数据添加到mlist中
        XDocument xDoc = XDocument.Load(m_XMLPath);
        XElement root = xDoc.Root;

        XElement assetBundleNode = root.Element("AssetBundle");

        IEnumerable itemList = assetBundleNode.Elements("Item");
        int keyIndex = 0;
        foreach(XElement item in itemList)
        {
            AssetBundleEntity abEntity = new AssetBundleEntity();
            abEntity.Key = "key" + ++keyIndex;
            abEntity.Name = item.Attribute("Name").Value;
            abEntity.Tag = item.Attribute("Tag").Value;
            abEntity.ToPath = item.Attribute("ToPath").Value;
            abEntity.Version = item.Attribute("Version").Value.ToInt();
            abEntity.Size = item.Attribute("Size").Value.ToLong();

            IEnumerable paths = item.Elements("Path");
            foreach(XElement path in paths)
            {
                abEntity.PathList.Add(string.Format(@"Assets\{0}", path.Attribute("Value").Value));
            }

            m_List.Add(abEntity);
        }

        return m_List;
    }
    #endregion
}

通过GetList()就可以直接获取到所有的entity实体了

下面进行EditorWindow的编写  -- 也就是可视化的AssetBundle界面编写

// AssetBundleWindow.cs
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;

public class AssetBundleWindow : EditorWindow
{ 
    private AssetBundleDAL abDAL = null;
    
    //AssetBundle实体列表
    private List assetBundleEntities = null;

    //字典 Assetbundle名字 - 是否打包选中
    private Dictionary m_Dict;
    
    //类型数组
    private string[] arrTag = { "All", "Scene", "Role", "Effect", "Audio", "None" };
    private int tagIndex = 0;

    //编译平台数组
    private string[] arrBuildTarget = { "Windows", "iOS", "Android" };

    string xmlpath = "";

    //ScrollView的Scroll位置
    private Vector2 pos;

#if UNITY_STANDALONE || UNITY_EDITOR
    private BuildTarget target = BuildTarget.StandaloneWindows;
    private int buildTargetIndex = 0;
#elif UNITY_IPHONE
    private BuildTarget target = BuildTarget.iOS;
    private int buildTargetIndex = 1;
#elif UNITY_ANDROID
    private BuildTarget target = BuildTarget.Android;
    private int buildTargetIndex = 2;
#endif

    void OnEnable()
    {
        // 自定义xmlpath 这里我写死了
        xmlpath = Application.dataPath + @"\Script\Editor\AssetBundleConfig.xml";

        m_Dict = new Dictionary();

        if (!string.IsNullOrEmpty(xmlpath))
        {
            abDAL = new AssetBundleDAL(xmlpath);
            assetBundleEntities = abDAL.GetList();
        }
        
        // 默认给所有的选项打勾
        for (int i = 0; i < assetBundleEntities.Count; i++)
        {
            m_Dict[assetBundleEntities[i].Key] = true;
        }
    }


    private void OnGUI()
    {
        if (assetBundleEntities == null) return;

        #region 按钮行
        GUILayout.BeginHorizontal("box");

        tagIndex = EditorGUILayout.Popup(tagIndex, arrTag, GUILayout.Width(100));
        if (GUILayout.Button("选定Tag", GUILayout.Width(100)))
        {
            EditorApplication.delayCall = OnSelectTagCallback;
        }

        buildTargetIndex = EditorGUILayout.Popup(buildTargetIndex, arrBuildTarget, GUILayout.Width(100));
        if (GUILayout.Button("选定Target", GUILayout.Width(100)))
        {
            EditorApplication.delayCall = OnSelectTargetCallback;
        }
        if (GUILayout.Button("打包AB包", GUILayout.Width(100)))
        {
            EditorApplication.delayCall = OnBuildAllAB;
        }
        if (GUILayout.Button("清除AB包", GUILayout.Width(100)))
        {
            EditorApplication.delayCall = OnCleanAB;
        }
        EditorGUILayout.Space();
        GUILayout.EndHorizontal();
        #endregion

        GUILayout.BeginHorizontal("box");
        GUILayout.Label("包名");
        GUILayout.Label("标记", GUILayout.Width(100));
        GUILayout.Label("保存路径", GUILayout.Width(200));
        GUILayout.Label("版本", GUILayout.Width(100));
        GUILayout.Label("大小", GUILayout.Width(100));
        GUILayout.EndHorizontal();

        GUILayout.BeginVertical();

        pos = EditorGUILayout.BeginScrollView(pos);
        for (int i = 0; i < assetBundleEntities.Count; i++)
        {
            AssetBundleEntity abe = assetBundleEntities[i];

            GUILayout.BeginHorizontal("box");
            m_Dict[assetBundleEntities[i].Key] = GUILayout.Toggle(m_Dict[assetBundleEntities[i].Key], abe.Name);
            GUILayout.Label(abe.Tag, GUILayout.Width(100));
            GUILayout.Label(abe.ToPath, GUILayout.Width(200));
            GUILayout.Label(abe.Version.ToString(), GUILayout.Width(100));
            GUILayout.Label(abe.Size + "K", GUILayout.Width(100));
            GUILayout.EndHorizontal();

            foreach (string path in abe.PathList)
            {
                GUILayout.BeginHorizontal("box");
                GUILayout.Space(40);
                GUILayout.Label(path);
                GUILayout.EndHorizontal();
            }
        }

        EditorGUILayout.EndScrollView();

        GUILayout.EndVertical();
    }

    /// 
    /// 清理AssetBundle
    /// 
    private void OnCleanAB()
    {
        //开始创建
        string toPath = Application.dataPath + "/../AssetBundles/" + arrBuildTarget[buildTargetIndex];

        if(Directory.Exists(toPath))
        {
            Directory.Delete(toPath, true);
            Debug.Log("删除成功");
        } 
    }

    /// 
    /// 打包AssetBundle
    /// 
    private void OnBuildAllAB()
    {
        for (int i = 0; i < assetBundleEntities.Count; i++)
        {
            if(m_Dict[assetBundleEntities[i].Key])
            { 
                BuildAssetBundle(assetBundleEntities[i]);
            }
        }
        Debug.Log("打包成功");
    }

    private void BuildAssetBundle(AssetBundleEntity entity)
    {
        AssetBundleBuild[] arrBuild = new AssetBundleBuild[1];
        AssetBundleBuild build = new AssetBundleBuild();

        //包名
        build.assetBundleName = entity.Name;
        //后缀
        if (entity.Tag.Equals("scene", StringComparison.CurrentCultureIgnoreCase))
        {
            build.assetBundleName += ".unity3d";
        }
        else
        {
            build.assetBundleName += ".assetbundle";
        }
        //资源路径
        build.assetNames = entity.PathList.ToArray();

        arrBuild[0] = build;

        //开始创建
        string toPath = Application.dataPath + "/../AssetBundles/" + arrBuildTarget[buildTargetIndex] + entity.ToPath;

        if (!Directory.Exists(toPath))
            Directory.CreateDirectory(toPath);
        
        BuildPipeline.BuildAssetBundles(toPath, arrBuild, BuildAssetBundleOptions.None, target);
    }

    /// 
    /// 选定Target回调
    /// 
    private void OnSelectTargetCallback()
    {
        //"Windows",  "iOS", "Android" 
        switch (buildTargetIndex)
        {
            case 0:
                target = BuildTarget.StandaloneWindows;
                buildTargetIndex = 0;
                break;
            case 1:
                target = BuildTarget.iOS;
                buildTargetIndex = 1;
                break;
            case 2:
                target = BuildTarget.Android;
                buildTargetIndex = 2;
                break;
        }
        Debug.Log("选定平台为:" + target.ToString());
    }

    /// 
    /// 选定Tag回调
    /// 
    private void OnSelectTagCallback()
    {
        //"All", "Scene", "Role", "Effect", "Audio", "None"
        switch (tagIndex)
        {
            case 0: //All
                foreach (AssetBundleEntity item in assetBundleEntities)
                {
                    m_Dict[item.Key] = true;
                }
                break;
            case 1: //Scene
                foreach (AssetBundleEntity item in assetBundleEntities)
                {
                    m_Dict[item.Key] = item.Tag.Equals("scene", StringComparison.CurrentCultureIgnoreCase);
                }
                break;
            case 2: //Role
                foreach (AssetBundleEntity item in assetBundleEntities)
                {
                    m_Dict[item.Key] = item.Tag.Equals("role", StringComparison.CurrentCultureIgnoreCase);
                }
                break;
            case 3: //Effect
                foreach (AssetBundleEntity item in assetBundleEntities)
                {
                    m_Dict[item.Key] = item.Tag.Equals("effect", StringComparison.CurrentCultureIgnoreCase);
                }
                break;
            case 4: //Audio
                foreach (AssetBundleEntity item in assetBundleEntities)
                {
                    m_Dict[item.Key] = item.Tag.Equals("audio", StringComparison.CurrentCultureIgnoreCase);
                }
                break;
            case 5: //None
                foreach (AssetBundleEntity item in assetBundleEntities)
                {
                    m_Dict[item.Key] = false;
                }
                break;
        }
    }
}

再新建一个类,把AssetBundleWindow实例化出来,就可以看到操作界面了

// CustomMenu.cs
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class Menu
{ 
    [MenuItem("MyTools/CreateAssetBundle")]
    public static void CreateAssetBundle()
    {
        AssetBundleWindow abWin = new AssetBundleWindow();
        abWin.titleContent = new GUIContent("资源管理");
        abWin.Show(); 
    }
}

最终效果图大概就是这样:

使用UnityEditor制作可视化打包AssetBundle(一)_第1张图片

 

各类路径解释:

PathList:存放的是各类资源在unity中的存放位置

"string toPath = Application.dataPath + "/../AssetBundles/" + arrBuildTarget[buildTargetIndex] + entity.ToPath;"

toPath这个是存放打包的assetbundle的,格式大概为:unity项目上一级目录/AssetBundles/平台名(win,Android,ios)/asset类型名/xxx.assetbundle

下一篇我会写加载AssetBundle,有什么错误或者建议的话,欢迎各位小伙伴留言。

你可能感兴趣的:(Unity)