本工具是基于Odin制作,方便查找對(duì)應(yīng)面板的UGUI組件钓株,并提供對(duì)應(yīng)腳本創(chuàng)建实牡、組件賦值、常規(guī)沖突檢測(cè)等機(jī)制轴合。
方便快捷易上手创坞,筆者已經(jīng)做好注釋,易于魔改受葛。(例如生成Lua文件等)题涨。
選擇要添加的類型
添加對(duì)應(yīng)類型的節(jié)點(diǎn)偎谁,不符合類型會(huì)報(bào)錯(cuò)
選擇UI分部類對(duì)應(yīng)的腳本文件
點(diǎn)擊【導(dǎo)出對(duì)應(yīng)分部類】按鈕,節(jié)點(diǎn)出現(xiàn)重名會(huì)有提示
點(diǎn)擊【為組件進(jìn)行賦值】按鈕進(jìn)行綁定
示例完整腳本
using Sirenix.OdinInspector;
using Sirenix.Utilities;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
public class UINodeCollection : MonoBehaviour
{
[SerializeField]
[ListDrawerSettings(DraggableItems = false, Expanded = false)]
private List<UINodeGroup> uINodes = new List<UINodeGroup>();
#region 編輯器
#if UNITY_EDITOR
const string k_Tab = " ";
public string className;
#pragma warning disable CS0649
[ShowInInspector]
[LabelText("選擇需要生成的分部類")]
[FilePath(Extensions = "cs, lua", AbsolutePath = true)]
private string filePath;
#pragma warning restore CS0649
[Button("導(dǎo)出對(duì)應(yīng)的分部類", ButtonSizes.Large)]
private void ExportPartialScript()
{
if (string.IsNullOrEmpty(filePath))
{
UnityEditor.EditorUtility.DisplayDialog("警告", "沒(méi)有選擇需要生成的分部類", "確定");
return;
}
if (IsHaveRepetitiveName()) return;
//獲取對(duì)應(yīng)的類名稱
var layerArray = filePath.Split(Path.AltDirectorySeparatorChar);
className = layerArray[layerArray.Length - 1].Split('.')[0];
//生成絕對(duì)路徑
string path = filePath.Replace(className, className + "Extention");
StringBuilder content = new StringBuilder();
//添加對(duì)應(yīng)的注釋
content.AppendLine(CreateAnnotation().ToString());
//添加命名空間
content.Append(AdditionalNamespacesToString());
//添加內(nèi)容
content.AppendLine("public partial class " + className + "\r\n" + "{\r\n");
for (int i = 0; i < uINodes.Count; i++)
{
content.AppendLine(CreateOneGroup(uINodes[i]));
}
content.AppendLine("}\r\n");
CreateScript(path, content);
UnityEditor.AssetDatabase.Refresh();
Debug.Log("生成代碼完畢");
}
[Button("為組件進(jìn)行賦值", ButtonSizes.Large)]
private void SetComponentValue()
{
string nameSpace = "Assembly-CSharp";
var assembly = Assembly.Load(nameSpace);
var tempType = assembly.GetType(className);
var type = transform.GetComponent(tempType);
var fieldInfos = type.GetType().GetFields();
for (int i = 0; i < fieldInfos.Length; i++)
{
var item = fieldInfos[i];
var targetType = item.FieldType;
var temp = uINodes.Where(a => a.typeName == targetType.Name)//篩選類型
.SelectMany(a => a.nodes)
.Where(t => t.name.Replace(" ", "") == item.Name)
.FirstOrDefault();
var targetValue = temp.gameObject.GetComponent(targetType);
item.SetValue(type, targetValue);
}
}
private StringBuilder CreateAnnotation()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("http://開發(fā)者:海瀾");
stringBuilder.AppendLine("http://描述:快速查找對(duì)應(yīng)UI組件節(jié)點(diǎn)及代碼綁定");
stringBuilder.AppendLine("http://腳本創(chuàng)建時(shí)間:" + DateTime.Now);
stringBuilder.AppendLine(
@"http://********************************
//本腳本為自動(dòng)創(chuàng)建【切勿更改】
//********************************");
return stringBuilder;
}
private string AdditionalNamespacesToString()
{
return
"using System;\r\n" +
"using System.Collections;\r\n" +
"using System.Collections.Generic;\r\n" +
"using System.IO;\r\n" +
"using System.Linq;\r\n" +
"using UnityEngine;\r\n" +
"using UnityEngine.UI;\r\n" +
"using Sirenix.OdinInspector; \r\n" +
"using TMPro; \r\n" +
"\r\n";
}
private string CreateOneGroup(UINodeGroup uINodeGroup)
{
string temp = "";
var nodes = uINodeGroup.nodes;
string typeName = uINodeGroup.typeName;
for (int i = 0; i < nodes.Count; i++)
{
temp += k_Tab + $"public {typeName} {nodes[i].name.Replace(" ", "")};\r\n";
}
return temp;
}
private void CreateScript(string fileName, StringBuilder content)
{
string path = fileName;
using (FileStream fs = new FileStream(path, FileMode.Create))
{
using (StreamWriter writer = new StreamWriter(fs, System.Text.Encoding.UTF8))
{
writer.Write(content.ToString());
}
}
}
private bool IsHaveRepetitiveName()
{
string content = "";
for (int i = 0; i < uINodes.Count; i++)
{
content += GetRepetitiveName(uINodes[i]);
}
if (!string.IsNullOrEmpty(content))
{
UnityEditor.EditorUtility.DisplayDialog("發(fā)現(xiàn)重復(fù)元素", content, "確定");
return true;
}
return false;
}
private string GetRepetitiveName(UINodeGroup uINodeGroup)
{
var nodes = uINodeGroup.nodes;
//先去重復(fù)
//然后查找對(duì)應(yīng)Key的個(gè)數(shù) 纲堵,大于1就是重復(fù)
List<string> strList = new List<string>();
for (int i = 0; i < nodes.Count; i++)
{
strList.Add(nodes[i].name);
}
var group = strList.GroupBy(str => str).Where(g => g.Count() > 1).Select(y => new { Element = y.Key, Counter = y.Count() }).ToList();
string content = "";
for (int i = 0; i < group.Count; i++)
{
content += $"重復(fù)元素:{group[i].Element} 重復(fù)的個(gè)數(shù)為:{group[i].Counter}";
}
return content;
}
#endif
#endregion
[Serializable]
private class UINodeGroup
{
#pragma warning disable CS0649
[LabelText("節(jié)點(diǎn)類型")]
[ValueDropdown("GetFilteredTypeList")]
public string typeName;
#pragma warning restore CS0649
[ChildGameObjectsOnly]
[ValidateInput("ValidateComponent", "填對(duì)對(duì)應(yīng)的組件非指定類型", InfoMessageType.Error)]
public List<UnityEngine.Component> nodes = new List<UnityEngine.Component>();
#region 編輯器
#if UNITY_EDITOR
/// <summary>
/// typeName類型過(guò)濾
/// </summary>
/// <returns></returns>
private IEnumerable<string> GetFilteredTypeList()
{
var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes())
.Where(t => !t.IsAbstract)
.Where(t => !t.IsGenericTypeDefinition)
.Where(t => typeof(Component).IsAssignableFrom(t))
.Where(t => t.Namespace == "UnityEngine.UI")
.Where(t => t.IsPublic);
types = types.AppendWith(typeof(Transform));
var typeNames = types.Select(t => t.Name);
return typeNames;
}
/// <summary>
/// 對(duì)添加節(jié)點(diǎn)類型的驗(yàn)證
/// </summary>
/// <param name="nodes"></param>
/// <returns></returns>
private bool ValidateComponent(List<UnityEngine.Component> nodes)
{
if (nodes.Count <= 0 || typeName == "Transform") return true;
string nameSpace = "UnityEngine.UI";
var node = nodes[nodes.Count - 1];
var assembly = Assembly.Load(nameSpace);
var tempType = assembly.GetType(nameSpace + "." + typeName);
var tempComponent = node.GetComponent(tempType);
return tempComponent != null;
}
#endif
#endregion
}
}