1051 字
5 分钟
Unity 编辑器扩展工具集

曲线工具#

这个工具用于生成和编辑 Unity 的 AnimationCurve 曲线,可以方便地将曲线数据转换为代码,也可以从代码中还原曲线。

using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
public class CurveTool : EditorWindow
{
private AnimationCurve curve;
private string target_Str = "";
[MenuItem("工具/曲线工具")]
public static void OpenWindow()
{
GetWindow<CurveTool>("曲线工具");
}
private void OnGUI()
{
GUILayout.Space(20f);
EditorGUILayout.CurveField(curve);
GUILayout.Space(20f);
if (GUILayout.Button("生成"))
{
target_Str = "";
target_Str += $"AnimationCurve curve;\n";
target_Str += $"Keyframe[] keyframes = new Keyframe[{curve.length}];\n";
for (int i = 0; i < curve.length; i++)
target_Str += $"keyframes[{i}] = new Keyframe({curve.keys[i].time}f, {curve.keys[i].value}f, {curve.keys[i].inTangent}f, {curve.keys[i].outTangent}f, {curve.keys[i].inWeight}f, {curve.keys[i].outWeight}f);\n";
target_Str += $"curve = new AnimationCurve(keyframes);";
}
GUILayout.Space(20f);
target_Str = GUILayout.TextArea(target_Str);
if (GUILayout.Button("复原"))
{
MatchCollection mc = Regex.Matches(target_Str, @"-*?\d+(\.\d+)*(?=f)");
List<Keyframe> keys = new List<Keyframe>();
Keyframe key = new Keyframe();
for (int i = 0; i < mc.Count; i++)
{
switch (i % 6)
{
case 0:
key = new Keyframe();
key.time = float.Parse(mc[i].Value);
break;
case 1:
key.value = float.Parse(mc[i].Value);
break;
case 2:
key.inTangent = float.Parse(mc[i].Value);
break;
case 3:
key.outTangent = float.Parse(mc[i].Value);
break;
case 4:
key.inWeight = float.Parse(mc[i].Value);
break;
case 5:
key.outWeight = float.Parse(mc[i].Value);
keys.Add(key);
break;
}
}
curve = new AnimationCurve(keys.ToArray());
}
}
}

正则测试工具#

这个工具提供了一个可视化的正则表达式测试环境,支持多种文本输入方式,包括自定义文本、脚本文件和 StepScript。

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
namespace PersonalTool
{
public class RegexTestTool : EditorWindow
{
public static RegexTestTool Tool;
private string regexStr;
private Vector2 scrollPos = Vector2.zero;
private string fileString;
private MatchCollection matches = null;
private string[] splits = null;
private string coverStr = "";
private int preFileType = 0;
private int fileType = 0;
private string filename = "";
private string fileID = "";
private bool isTrans = true;
[MenuItem("工具/正则测试工具")]
private static void OpenWindow()
{
Tool = GetWindow<RegexTestTool>("正则测试工具");
Tool.Show();
}
private void OnEnable()
{
using (StreamReader sr = new StreamReader(Application.dataPath + "<FILE_PATH>"))
{
fileString = sr.ReadToEnd();
}
}
private void OnGUI()
{
GUILayout.Label("正则表达式");
regexStr = GUILayout.TextArea(regexStr);
EditorGUILayout.BeginHorizontal();
fileType = GUILayout.Toolbar(fileType, new string[] { "自定义文本", "脚本", "StepScript" });
if (preFileType != fileType)
{
coverStr = "";
fileID = "";
preFileType = fileType;
}
EditorGUILayout.EndHorizontal();
switch (fileType)
{
case 0:
GUILayout.Label("覆盖测试文本");
coverStr = GUILayout.TextArea(coverStr);
break;
case 1:
EditorGUILayout.BeginHorizontal();
GUILayout.Label("脚本名称");
filename = GUILayout.TextField(filename);
if (GUILayout.Button("确定"))
{
if (CheckInput(filename, out string id))
{
string filePath = Application.dataPath + $"<FILE_PATH>";
if (File.Exists(filePath))
{
fileID = id;
coverStr = File.ReadAllText(filePath);
}
}
}
EditorGUILayout.EndHorizontal();
GUILayout.Label($"当前脚本:{(fileID == "" ? "<FILE_NAME>" : fileID)}");
break;
case 2:
if (File.Exists(Application.dataPath + $"/.StepEditorProgram/StepScript.txt"))
{
coverStr = File.ReadAllText(Application.dataPath + $"/.StepEditorProgram/StepScript.txt");
}
GUILayout.Label($"StepScript 加载{(coverStr == "" ? "失败" : "成功")}");
isTrans = GUILayout.Toggle(isTrans, "是否转义回正常符号");
break;
}
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Match"))
{
if (regexStr == null || regexStr == "") return;
matches = null;
splits = null;
matches = Regex.Matches(coverStr != "" ? coverStr : fileString, regexStr, RegexOptions.ExplicitCapture);
//var obj = AssetDatabase.LoadAssetAtPath<Object>("<FILE_PATH>");
//Selection.activeObject = obj;
//EditorGUIUtility.PingObject(obj);
//Regex.Match("12", @"{[^{}]*(((?'Open'{)[^{}]*)+((?'-Open'})[^{}]*)+)*(?(Open)(?!))}");
//Regex.Match("12", @"[\x20\t]+case\s+\d+\s*:[\s\S]*?break;");
//Regex.Match("12", @"public\s+(async\s+)?override\s+(async\s+)?void\s+(command(Start|Update|End))[^{]*?{((?<open>{)|(?<-open>})|[^{}])*(?(open)(?!))}\s*(#HH#)+");
//Regex.Match("12", @"(?<=#HH#)\s*switch\s*\(StepController\.Instance\.currentIndex\)[^{]*?{((?<open>{)|(?<-open>})|[^{}])*(?(open)(?!))}\s*(#HH#)+");
}
if (GUILayout.Button("Split"))
{
if (regexStr == null || regexStr == "") return;
matches = null;
splits = null;
splits = Regex.Split(coverStr != "" ? coverStr : fileString, regexStr, RegexOptions.ExplicitCapture);
}
EditorGUILayout.EndHorizontal();
if (GUILayout.Button("清除"))
{
matches = null;
splits = null;
}
if (matches != null && matches.Count != 0)
{
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
foreach (Match m in matches)
{
string temp = "";
if (isTrans)
{
temp = m.Value.Replace("#HH#", "\n");
temp = temp.Replace("#SYH#", "\"");
}
EditorGUILayout.TextArea(isTrans ? temp : m.Value);
}
EditorGUILayout.EndScrollView();
}
if (splits != null && splits.Length != 0)
{
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
foreach (string s in splits)
{
string temp = "";
if (isTrans)
{
temp = s.Replace("#HH#", "\n");
temp = temp.Replace("#SYH#", "\"");
}
EditorGUILayout.TextArea(isTrans ? temp : s);
}
EditorGUILayout.EndScrollView();
}
}
private bool CheckInput(string inputStr, out string id)
{
id = null;
if (Regex.IsMatch(inputStr, @"^[Ee]+\d+[Cc]+\d+$"))
{
id = Regex.Replace(inputStr, @"[Ee]+", "E");
id = Regex.Replace(id, @"[Cc]+", "C");
return true;
}
return false;
}
}
}

文件创建扩展#

这个扩展提供了自定义的文件创建功能,包括 MLab 脚本、普通脚本和文本文件的创建,并支持自动替换文件模板中的关键字。

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
namespace PersonalTool.FileExtension
{
public class FileCreateExtension : EditorWindow
{
private const string MLAB_SCRIPT_TEMPLATE_PATH = "Assets/Editor/PersonalTool/FileExtension/MLabScriptTemplate.txt";
[MenuItem("Assets/Create/MLab Script (.cs)", false, 31)]
public static void CreateFile_MLabScript()
{
string filePath = AssetDatabase.GenerateUniqueAssetPath(GetSelectedPathOrFallback() + "NewMLabScript.cs");
ProjectWindowUtil.CreateAssetWithContent(filePath, File.ReadAllText(MLAB_SCRIPT_TEMPLATE_PATH), EditorGUIUtility.FindTexture("d_cs Script Icon"));
}
private const string NORMAL_SCRIPT_TEMPLATE_PATH = "Assets/Editor/PersonalTool/FileExtension/NormalScriptTemplate.txt";
[MenuItem("Assets/Create/Normal Script (.cs)", false, 31)]
public static void CreateFile_NormalScript()
{
string filePath = AssetDatabase.GenerateUniqueAssetPath(GetSelectedPathOrFallback() + "NewNormalScript.cs");
ProjectWindowUtil.CreateAssetWithContent(filePath, File.ReadAllText(NORMAL_SCRIPT_TEMPLATE_PATH), EditorGUIUtility.FindTexture("d_cs Script Icon"));
}
[MenuItem("Assets/Create/Text Asset (.txt)", false, 31)]
public static void CreateFile_TextAsset()
{
string filePath = AssetDatabase.GenerateUniqueAssetPath(GetSelectedPathOrFallback() + "New Text Asset.txt");
ProjectWindowUtil.CreateAssetWithContent(filePath, "", EditorGUIUtility.FindTexture("d_TextAsset Icon"));
}
private static string GetSelectedPathOrFallback()
{
string path = "Assets";
foreach (UnityEngine.Object obj in Selection.GetFiltered<UnityEngine.Object>(SelectionMode.Assets))
{
path = AssetDatabase.GetAssetPath(obj);
if (!string.IsNullOrEmpty(path) && File.Exists(path))
{
path = Path.GetDirectoryName(path);
break;
}
}
return path + "/";
}
}
public class CustomFileProcessor : UnityEditor.AssetModificationProcessor
{
public const string CompanyName = "moolsnet";
public const string Author = "请署名";
public const string Version = "1.0";
private static void OnWillCreateAsset(string path)
{
path = path.Replace(".meta", "");
if (!path.EndsWith(".cs")) return;
string content = File.ReadAllText(path);
if (!Regex.IsMatch(content, @"#CutsomClassName#")) return;
content = ReplaceKeywords(content, path);
File.WriteAllText(path, content);
AssetDatabase.Refresh();
}
public static string ReplaceKeywords(string input, string filePath)
{
input = input.Replace("#FileName#", Path.GetFileName(filePath));
input = input.Replace("#CompanyName#", CompanyName);
input = input.Replace("#Author#", Author);
input = input.Replace("#CreateTime#", DateTime.Now.ToString("F"));
input = input.Replace("#Version#", Version);
input = input.Replace("#UnityVersion#", Application.unityVersion);
input = input.Replace("#CutsomClassName#", Path.GetFileNameWithoutExtension(filePath));
return input;
}
}
}
Unity 编辑器扩展工具集
https://blog.unknowncat2048.top/posts/unity-editor-extension-archive/
作者
碌碌无为喵神SAMA
发布于
2024-08-01
许可协议
CC BY-NC-SA 4.0