Unity有个很烦人的规则:只要继承于MonoBehaviour类的脚本必须要达成文件名与类名相等,然而在Unity编辑器中重命名一个集成与MonoBehaviour的脚本并不会重命名脚本里的class name。于是我们经常重命名完一个脚本的文件名,Unity编译一次;然后进入脚本编辑软件把该脚本的class name重命名保存,Unity再编译一次。
This is such a waste of time and human resources!
所以我今天忍不住写了一段一键重命名的Editor小脚本分享给大家。
脚本的限制:
a. 该脚本只重命名与文件名相同的类名。
b. 重命名一个脚本并不会更新其它脚本对该脚本名称的引用。
using UnityEngine;
using UnityEditor;
using System.Text.RegularExpressions;
using System.IO;
[CustomEditor(typeof(MonoScript))]
public class ScriptRenameEditor : Editor
{
private string fileName = "";
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var t = target as MonoScript;
EditorGUILayout.BeginHorizontal();
var width = Screen.width * 2f / 3f;
//显示文本框让用户输入新的文件名
fileName = EditorGUILayout.TextField("New Filename", fileName, GUILayout.Width(width));
if (GUILayout.Button("Rename"))
{
//匹配文件名和父类的名字
var match = Regex.Match(t.text, @"class\s*(?<filename>" + t.name + @")\s*(\s*:\s*(?<basetype>[a-zA-Z0-9\_]+))?\s*\{");
if (match.Success)
{
var name = t.name;
var index = match.Groups["filename"].Index;
var finalText = t.text.Substring(0, index) + fileName + t.text.Substring(index + name.Length);
var filePath = AssetDatabase.GetAssetPath(t);
Debug.Log("renaming " + filePath);
//如果不存在父类,或者父类的名字不叫MonoBehaviour就弹窗警告用户.
if (match.Groups["basetype"] == null || match.Groups["basetype"].Value != "MonoBehaviour")
{
if (!EditorUtility.DisplayDialog("This script is not derived by MonoBehaviour", "do you really want to rename it?", "yes", "no"))
{
return;
}
}
using (var fs = File.Open(filePath, FileMode.Truncate))
using (var wr = new StreamWriter(fs, System.Text.Encoding.UTF8))
{
wr.Write(finalText);
}
var fi = new FileInfo(filePath);
File.Move(filePath, fi.DirectoryName + Path.DirectorySeparatorChar + fileName + fi.Extension);
AssetDatabase.Refresh();
Selection.activeObject = AssetDatabase.LoadAssetAtPath<Object>(filePath.Replace(name, fileName));
}
else
{
Debug.Log("no class named \"" + t.name + "\" was found.");
}
}
EditorGUILayout.EndHorizontal();
//显示文件的预览内容
if (t != null)
{
var text = t.text;
if (text.Length > 1000)
text = text.Substring(0, 1000) + "\n\n\n ...";
GUILayout.TextArea(text);
}
}
private void OnEnable()
{
var t = target as MonoScript;
fileName = t.name;
}
}
最终的效果如下: