Unity Editor扩展
最近在看热更新和编辑器扩展,于是想着就把打包AssetBundle的过程在Editor里面进行实现。
背景描述:
AssetBundle的打包,之前是需要进行自己输入代码进行打包的。虽然可以放到Editor里进行一件执行,但是涉及到较多的文件时,还是需要将路径一个一个敲进代码里。
要实现的功能:
当涉及较多的Asset需要打包时,就只需要通过打开文件夹的方式选中就可以了。将代码部分取消掉。
实现思路:
根据Unity给的API可以知道大概的思路
- 我们需要的数据:AssetBundle名、AssetBundle要存储的路径、还有每个Asset名(相对路径)
- 数据怎么存储:AssetBundle名和AssetBundle要存储的路径比较简单,可以作为一个全局变量进行调用。每个Asset的存储就稍微麻烦一点了,主要涉及到每个Asset的存储和删除。开始时使用的是字符串数组,但是做了很多无用功之后,发现,只是使用字符串数据是存在几个比较大的缺陷:(1)怎么将每个Asset的信息和浏览的功能绑定在一起(2)删除的功能,如果使用数组,那么需要将额外的实现。
- 最终方案:最后觉得还是觉得使用泛型List比较好(还想过使用链表,不过还没实现)。对于每个Asset信息的存取和删除,想着还是将它们集成到一个类里面会比较方便,所以声明一个Element类进行信息的存取和删除
下面是源码:
public class Element
{
public int ID;
public string path = "";
string root = "Assets";
public bool isActive = true;
public Element()
{ }
public void TextFieldElement()
{
GUILayout.BeginHorizontal();
GUILayout.Space(30);
path = EditorGUILayout.TextField("资源:", path, GUILayout.Width(324));
path = ReferenceButton();
DestoryButton();
GUILayout.EndHorizontal();
}
/// <summary>
/// 单击按钮获取相对路径
/// </summary>
/// <returns></returns>
public string ReferenceButton()
{
if (GUILayout.Button("浏览", GUILayout.Width(65)))
{
path = EditorUtility.OpenFilePanel("选取资源", "", "*");
}
if (path != "" && path != null)
{
int index = path.LastIndexOf(root);
path = path.Substring(index);
}
return path;
}
public void DestoryButton()
{
if (GUILayout.Button("删除", GUILayout.Width(65)))
{
isActive = false;
Debug.Log(isActive);
}
}
}
下面是编辑器部分的代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class BuildAssetBundles : EditorWindow
{
Vector2 scrollPos;
static int _abElementsCount;
string root = "Assets";
static string _sourcePath;
static string _AssetBundleName;
static string[] _abElementsPath;
List<Element> textCom = new List<Element>();
#region InitialEditor
[MenuItem("Tools/BuildAssetBundle")]
private static void InitializeEditor()
{
GetWindow<BuildAssetBundles>();
_abElementsCount = 0;
_sourcePath = "";
}
#endregion
private void Update()
{
if (textCom.Count != 0)
{
for (int i = 0; i < textCom.Count; i++)
{
if (textCom[i].isActive == false)
{
textCom.Remove(textCom[i]);
_abElementsCount--;
}
}
}
}
private void OnGUI()
{
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
//资源包名称
_AssetBundleName = AssetBundleName(_AssetBundleName);
//资源包路径
_sourcePath = AssetBundlePath(_sourcePath);
//资源包容量
_abElementsCount = UpdateElementsCount(_abElementsCount);
if (textCom.Count != 0)
{
foreach (var item in textCom)
{
item.TextFieldElement();
}
}
#region 使用List<T>
if (GUILayout.Button("添加", GUILayout.Width(200)))
{
Element temp = new Element();
textCom.Add(temp);
_abElementsCount++;
}
#endregion
//打包资源
if (GUILayout.Button("打包", GUILayout.Width(200)))
{
_abElementsPath = new string[textCom.Count];
for (int i = 0; i < textCom.Count; i++)
{
_abElementsPath[i] = textCom[i].path;
}
PackAssetBundles();
ShowNotification(new GUIContent("打包完成"));
}
//显示信息
if (GUILayout.Button("显示信息", GUILayout.Width(200)))
{
for (int i = 0; i < _abElementsPath.Length; i++)
{
Debug.Log(i + ":" + _abElementsPath[i]);
}
}
EditorGUILayout.EndScrollView();
}
//资源包命名
private string AssetBundleName(string assetBundleName)
{
GUILayout.BeginHorizontal();
assetBundleName = EditorGUILayout.TextField("资源包名称:", assetBundleName, GUILayout.Width(350));
if (GUILayout.Button("清空", GUILayout.Width(65)))
{
assetBundleName = "";
//EditorUtility.FocusProjectWindow();
}
GUILayout.EndHorizontal();
return assetBundleName;
}
private string AssetBundlePath(string assetBundlePath)
{
GUILayout.BeginHorizontal();
assetBundlePath = EditorGUILayout.TextField("资源包路径:", assetBundlePath, GUILayout.Width(350));
if (GUILayout.Button("浏览", GUILayout.Width(65)))
{
assetBundlePath = EditorUtility.OpenFolderPanel("选择文件夹", "Assets/", "");
}
if (assetBundlePath != "" && assetBundlePath != null)
{
int index = assetBundlePath.LastIndexOf(root);
assetBundlePath = assetBundlePath.Substring(index);
}
GUILayout.EndHorizontal();
return assetBundlePath;
}
private int UpdateElementsCount(int assetElementCount)
{
GUILayout.BeginHorizontal();
EditorGUILayout.LabelField(new GUIContent("资源包容量:"), GUILayout.Width(145));
GUILayout.Label(_abElementsCount.ToString(), GUILayout.Width(100));
GUILayout.EndHorizontal();
return assetElementCount;
}
public void PackAssetBundles()
{
AssetBundleBuild[] build = new AssetBundleBuild[1];
build[0].assetBundleName = _AssetBundleName;
build[0].assetNames = _abElementsPath;
BuildPipeline.BuildAssetBundles(_sourcePath, build, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
}
}
效果图:
注意:这个脚本必须放在Editor文件夹下面,否则会报错无法进行BuildAssetBundles;