为了让我们在运行时能够只使用名字即可加载界面,我们在创建了一个用于储存的.asset文件后,我们就需要考虑如何写入这个文件的值。
这里我们需要一个编辑器类,这个类实现了修改.asset文件内容、创建对应的脚本。
首先我们需要写一个UIEidtor继承Editor,脚本记得放在Editor文件夹下,然后写一个静态函数,用于一键调用我们自己写的功能。
如下代码即实现了编辑器中选中物体后右键处理逻辑
[MenuItem("Assets/Create/注册Panel", false, 1)]
public static void RegisterPanel()
{}
然后我们需要获取选中物体,并且取出其名字将其赋值到UIConfig.Instance.m_UIList中,即上述的.asset文件中
/// <summary>
/// 在Resources/UIConfig中注册此Panel
/// 如果后期需要删除可以到UIConfig中删除
/// 后面需要调用UI的时候,从UIConfig中调用
/// </summary>
[MenuItem("Assets/Create/注册Panel", false, 1)]
public static void RegisterPanel()
{
//获取全部选中物体GUID
string[] GUIDs = Selection.assetGUIDs;
//获取全部选中的物体
GameObject[] selecteObjects = Selection.gameObjects;
for (int i = 0; i < GUIDs.Length; i++)
{
//Debug.Log(AssetDatabase.GUIDToAssetPath(GUIDs[i]));
string name = "";
string path = "";
//将文件路径拆成文件名和父文件夹
//如:Asset/UI/test.png 会拆解为test.png和Asset/UI
Help.GetFileNameAndPath(AssetDatabase.GUIDToAssetPath(GUIDs[i]), out name, out path);
name = Help.GetFileName(name);
//Debug.Log("name:" + name);
//Debug.Log("path:" + path);
if (!Help.IsContainPanel(UIConfig.Instance.m_UIList, name))
{
//创建一个UIPanelConfig
UIPanelConfig item = new UIPanelConfig();
item.Name = name;
//在数组中搜索名字相同的object
//主要是应用于Selection.gameObjects遍历选中物体时,通过路径获取选中的GameObject
item.GameObject = Help.SearchObjectName(ref selecteObjects, name);
//增加Panel 完成注册
UIConfig.Instance.m_UIList.Add(item);
//在指定路径下创建UI脚本,此处Scripts/UI即为父路径,可以自行定义
CreateScript("Scripts/UI", item.Name);
Debug.Log("Panel注册成功:" + name);
}
else
{
Debug.LogError("当前Panel已注册,请勿重复注册:" + name);
}
}
//刷新编辑器
AssetDatabase.Refresh();
}
实现注册后UIConfig文件中会获取到绑定的Perfab和名字:
除了要创建还可以移除,也可以自行扩充一键清除等功能
全部代码如下:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using static UIConfig;
public class UIEidtor : Editor
{
/// <summary>
/// 在Resources/UIConfig中注册此Panel
/// 如果后期需要删除可以到UIConfig中删除
/// 后面需要调用UI的时候,从UIConfig中调用
/// </summary>
[MenuItem("Assets/Create/注册Panel", false, 1)]
public static void RegisterPanel()
{
//获取全部选中物体GUID
string[] GUIDs = Selection.assetGUIDs;
//获取全部选中的物体
GameObject[] selecteObjects = Selection.gameObjects;
for (int i = 0; i < GUIDs.Length; i++)
{
//Debug.Log(AssetDatabase.GUIDToAssetPath(GUIDs[i]));
string name = "";
string path = "";
//将文件路径拆成文件名和父文件夹
//如:Asset/UI/test.png 会拆解为test.png和Asset/UI
Help.GetFileNameAndPath(AssetDatabase.GUIDToAssetPath(GUIDs[i]), out name, out path);
name = Help.GetFileName(name);
//Debug.Log("name:" + name);
//Debug.Log("path:" + path);
if (!Help.IsContainPanel(UIConfig.Instance.m_UIList, name))
{
//创建一个UIPanelConfig
UIPanelConfig item = new UIPanelConfig();
item.Name = name;
//在数组中搜索名字相同的object
//主要是应用于Selection.gameObjects遍历选中物体时,通过路径获取选中的GameObject
item.GameObject = Help.SearchObjectName(ref selecteObjects, name);
//增加Panel 完成注册
UIConfig.Instance.m_UIList.Add(item);
//在指定路径下创建UI脚本,此处Scripts/UI即为父路径,可以自行定义
CreateScript("Scripts/UI", item.Name);
Debug.Log("Panel注册成功:" + name);
}
else
{
Debug.LogError("当前Panel已注册,请勿重复注册:" + name);
}
}
//刷新编辑器
AssetDatabase.Refresh();
}
/// <summary>
/// 清除选中的Panel注册状态
/// </summary>
[MenuItem("Assets/Create/清除Panel注册状态", false, 1)]
public static void RemovePanel()
{
string[] GUIDs = Selection.assetGUIDs;
GameObject[] selecteObjects = Selection.gameObjects;
for (int i = 0; i < GUIDs.Length; i++)
{
//Debug.Log(AssetDatabase.GUIDToAssetPath(GUIDs[i]));
string name = "";
string path = "";
Help.GetFileNameAndPath(AssetDatabase.GUIDToAssetPath(GUIDs[i]), out name, out path);
name = Help.GetFileName(name);
if (Help.IsContainPanel(UIConfig.Instance.m_UIList, name))
{
UIPanelConfig item = new UIPanelConfig();
item.Name = name;
item.GameObject = Help.SearchObjectName(ref selecteObjects, name);
UIConfig.Instance.m_UIList.Remove(item);
Debug.Log("Panel清除成功:" + name);
}
else
{
Debug.LogError("当前Panel未注册:" + name);
}
}
AssetDatabase.Refresh();
}
//[MenuItem("Assets/Create/创建脚本", false, 1)]
public static void CreateScript(string path, string uIName)
{
string folderPath = Application.dataPath + "/" + path;
TextAsset uIItemTextFile = Resources.Load("UIControl", typeof(TextAsset)) as TextAsset;
string contents = "";
if (uIItemTextFile != null)
{
contents = uIItemTextFile.text;
contents = contents.Replace("CHARACTERCLASS_NAME_HERE", uIName.Trim().Replace(" ", "") + "_UIControl");
}
Help.FolderPathExist(folderPath);
AssetDatabase.Refresh();
string filePath = string.Format(folderPath + "/{0}.cs", new object[] { uIName.Replace(" ", "") });
if (!Help.FilePathExist(filePath))
{
//存在同名文件则不创建
using (StreamWriter sw = new StreamWriter(filePath))
{
sw.Write(contents);
}
AssetDatabase.Refresh();
}
else
{
Debug.Log("当前脚本已存在:" + filePath);
}
}
}
这里用到了一些小功能,我全部整理到一个帮助工具类中:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using static UIConfig;
public static class Help
{
/// <summary>
/// 拆解url路径为文件名和路径,如Assets/Resources/x.asset
/// 会通过out返回name:x.asset
/// path:Assets/Resources
/// </summary>
/// <param name="url"></param>
/// <param name="name"></param>
/// <param name="path"></param>
public static void GetFileNameAndPath(string url, out string name, out string path)
{
if (!url.Contains("/"))
{
name = url;
path = url;
return;
}
int indexOfLastFolder = url.LastIndexOf("/");
name = url.Substring(indexOfLastFolder + 1, url.Length - indexOfLastFolder - 1);
path = url.Substring(0, indexOfLastFolder);
}
/// <summary>
/// 移除文件名后缀
/// 如666.mp3转换后会获得666
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public static string GetFileName(string file)
{
if (!file.Contains("."))
{
return file;
}
int indexOfPoint = file.LastIndexOf(".");
return file.Substring(0, indexOfPoint);
}
/// <summary>
/// 在数组中搜索名字相同的object
/// 主要是应用于Selection.gameObjects遍历选中物体时,通过路径获取选中的GameObject
/// </summary>
/// <param name="objects"></param>
/// <param name="name"></param>
/// <returns></returns>
public static GameObject SearchObjectName(ref GameObject[] gameObjects, string name)
{
foreach (GameObject gameObject in gameObjects)
{
if (gameObject.name.Equals(name))
{
return gameObject;
}
}
return null;
}
/// <summary>
/// 测试总UI列表中是否包含此名字的Panel
/// </summary>
/// <param name="uIItems"></param>
/// <param name="name"></param>
/// <returns></returns>
public static bool IsContainPanel(List<UIPanelConfig> uIItems, string name)
{
foreach (var item in uIItems)
{
if (item.Name.Equals(name))
return true;
}
return false;
}
/// <summary>
/// 测试总UI列表中是否包含此名字的Panel
/// </summary>
/// <param name="uIItems"></param>
/// <param name="name"></param>
/// <returns></returns>
public static bool IsContainPanel(List<UIPanelConfig> uIItems, string name, out UIPanelConfig uIItem)
{
uIItem = default;
foreach (var item in uIItems)
{
if (item.Name.Equals(name))
{
uIItem = item;
return true;
}
}
return false;
}
/// <summary>
/// 判断文件夹路径是否存在,如果不存在则创建
/// </summary>
/// <param name="path"></param>
public static void FolderPathExist(string path)
{
DirectoryInfo directoryInfo = new DirectoryInfo(path);
if (!directoryInfo.Exists)
{
Directory.CreateDirectory(path);
}
}
/// <summary>
/// 判断文件路径是否存在
/// </summary>
/// <param name="path"></param>
public static bool FilePathExist(string path)
{
FileInfo fileInfo = new FileInfo(path);
return fileInfo.Exists;
}
}