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();
}
}
最终效果图大概就是这样:
各类路径解释:
PathList:存放的是各类资源在unity中的存放位置
"string toPath = Application.dataPath + "/../AssetBundles/" + arrBuildTarget[buildTargetIndex] + entity.ToPath;"
toPath这个是存放打包的assetbundle的,格式大概为:unity项目上一级目录/AssetBundles/平台名(win,Android,ios)/asset类型名/xxx.assetbundle
下一篇我会写加载AssetBundle,有什么错误或者建议的话,欢迎各位小伙伴留言。