Unity 工具 之 实现简单的添加脚本命名空间 Namespace 的小工具(不改动原始脚本模板)?
目录
Unity 工具 之 实现简单的添加脚本命名空间 Namespace 的小工具(不改动原始脚本模板)?
一、简单介绍
二、实现原理
三、注意事项
四、效果预览
五、实现步骤
?六、关键代码
一、简单介绍
Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。
本节介绍,如何不修改原始脚本模板的情况下,添加自己需要的命名空间Namespace的方法,这里简单说明,如果你有更好的方法,欢迎留言交流。 ?
二、实现原理
1、使用 UnityEditor.AssetModificationProcessor 在脚本创建的时候,进行脚本修改命名空间添加
2、MenuItem 、EditorWindow、OnGUI 进行菜单工具,可视化修改命名空间
三、注意事项
1、这里只是添加命名空间的简单使用,需要更高级的设置,可能需要你额外设置,这里只是抛砖引玉哈
2、注意 Config 文件的一些修改,如果你的文件夹结构,和我的不一致
3、勾选启用,才会添加指定命名空间
四、效果预览
五、实现步骤
1、打开 Unity,新建一个空工程
2、设置工程中文件夹结构,并添加脚本,实现添加自动添加命名空间Namespace 的功能
?????????
3、在菜单栏上,可以看见脚本实现的工具
4、设置自己的命名空间 Namespace ,然后勾选开启,点击确定,指定位置会生成你的数据文件
5、新建一个脚本,即可看到,自己的脚本添加上了指定的命名空间
?
?六、关键代码
1、AddNamespaceWindow
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace XANTools.Editor {
/// <summary>
/// 自动添加命名空间的,可视化设置窗口脚本
/// </summary>
public class AddNamespaceWindow : EditorWindow
{
private static string _name;
public static bool _isOn;
[MenuItem("Tools/AddNamespace")]
public static void OpenWindow()
{
var window = GetWindow(typeof(AddNamespaceWindow));
window.minSize = new Vector2(500, 300);
window.Show();
Init();
}
public static NamespaceData GetData()
{
return AssetDatabase.LoadAssetAtPath<NamespaceData>(PathConfig.NAMESPACE_DATA_ASSET_PATH);
}
private static void Init()
{
NamespaceData data = GetData();
if (data != null)
{
_name = data.name;
_isOn = data.IsOn;
}
}
private void OnGUI()
{
GUILayout.Label("命名空间名称");
Rect rect = EditorGUILayout.GetControlRect(GUILayout.Width(200));
_name = EditorGUI.TextField(rect, _name);
_isOn = GUILayout.Toggle(_isOn, "是否开启脚本自动添加或者更新指定命名空间的功能");
if (GUILayout.Button("确定", GUILayout.MaxWidth(100)))
{
NamespaceData data = new NamespaceData();
data.name = _name;
data.IsOn = _isOn;
Directory.CreateDirectory(PathConfig.NAMESPACE_DATA_ROOT_PATH);
AssetDatabase.CreateAsset(data, PathConfig.NAMESPACE_DATA_ASSET_PATH);
}
}
}
}
2、AutoAddNameSpace
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
namespace XANTools.Editor {
/// <summary>
/// 自动添加命名空间的脚本
/// 其实是重写脚本内容
/// </summary>
public class AutoAddNameSpace : UnityEditor.AssetModificationProcessor
{
private static void OnWillCreateAsset(string path)
{
if (!IsOn())
return;
path = path.Replace(".meta", "");
if (path.EndsWith(".cs"))
{
string text = "";
text += File.ReadAllText(path);
string name = GetClassName(text);
if (string.IsNullOrEmpty(name))
{
return;
}
var newText = GetNewScriptContext(name);
File.WriteAllText(path, newText);
}
AssetDatabase.Refresh();
}
public static NamespaceData GetData()
{
return AssetDatabase.LoadAssetAtPath<NamespaceData>(PathConfig.NAMESPACE_DATA_ASSET_PATH);
}
private static bool IsOn()
{
NamespaceData data = GetData();
if (data != null)
{
return data.IsOn;
}
return false;
}
//获取新的脚本内容
private static string GetNewScriptContext(string className)
{
var script = new ScriptBuildHelp();
script.WriteUsing("UnityEngine");
script.WriteEmptyLine();
var data = AddNamespaceWindow.GetData();
string name = data == null ? NamespaceConfig.DEFAULT_NAMESPACE_NAME : data.name;
script.WriteNamespace(name);
script.IndentTimes++;
script.WriteClass(className, "MonoBehaviour");
script.IndentTimes++;
List<string> keys = new List<string>();
keys.Add("void");
script.WriteFun(keys, "Start");
return script.ToString();
}
//获取类名
private static string GetClassName(string text)
{
// 传统的方式
//return CommonGetClassName(text);
// 正则表达式的方式
return RexGetClassName(text);
}
/// <summary>
/// 传统方法获取
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
static string CommonGetClassName(string text) {
string[] data = text.Split(' ');
int index = 0;
for (int i = 0; i < data.Length; i++)
{
if (data[i].Contains("class"))
{
index = i + 1;
break;
}
}
if (data[index].Contains(":"))
{
return data[index].Split(':')[0];
}
else
{
return data[index];
}
}
/// <summary>
/// 正则表达式的方式
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
static string RexGetClassName(string text) {
string patterm = "public class ([A-Za-z0-9_]+)\\s*:\\s*MonoBehaviour"; // 例如:public class NewBehaviourScript : MonoBehaviour
var match = Regex.Match(text, patterm);
if (match.Success)
{
return match.Groups[1].Value;
}
return "";
}
}
}
3、NamespaceData
using UnityEngine;
namespace XANTools.Editor {
[System.Serializable]
public class NamespaceData : ScriptableObject
{
[SerializeField]
public string name;
[SerializeField]
public bool IsOn;
}
}
4、ScriptBuildHelp
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
namespace XANTools.Editor {
/// <summary>
/// 辅助脚本内容的改写
/// </summary>
public class ScriptBuildHelp
{
public static string Public = "public";
public static string Private = "private";
public static string Protected = "protected";
private StringBuilder _stringBuilder;
private string _lineBrake = "\r\n";
private int currentIndex = 0;
public int IndentTimes { get; set; }
/// <summary>
/// 回到大括号中间,需要缩进的值
/// </summary>
private int _backNum
{
get { return (GetIndent() + "}" + _lineBrake).Length; }
}
public ScriptBuildHelp()
{
_stringBuilder = new StringBuilder();
ResetData();
}
public void ResetData()
{
_stringBuilder.Clear();
currentIndex = 0;
}
private void Write(string context, bool needIndent = true)
{
if (needIndent)
{
context = GetIndent() + context;
}
if (currentIndex == _stringBuilder.Length)
{
_stringBuilder.Append(context);
}
else
{
_stringBuilder.Insert(currentIndex, context);
}
currentIndex += context.Length;
}
public void WriteLine(string context, bool needIndent = false)
{
Write(context + _lineBrake, needIndent);
}
private string GetIndent()
{
string indent = "";
for (int i = 0; i < IndentTimes; i++)
{
indent += " ";
}
return indent;
}
/// <summary>
/// 返回值为回到大括号中间,需要缩进的值
/// </summary>
/// <returns></returns>
private int WriteCurlyBrackets()
{
var start = _lineBrake + GetIndent() + "{" + _lineBrake;
var end = GetIndent() + "}" + _lineBrake;
Write(start + end);
return end.Length;
}
public void WriteUsing(string nameSpaceName)
{
WriteLine("using " + nameSpaceName + ";");
}
public void WriteEmptyLine()
{
WriteLine("");
}
public void WriteNamespace(string name)
{
Write("namespace " + name);
WriteCurlyBrackets();
BackToInsertContent();
}
public void WriteClass(string name, params string[] baseName)
{
StringBuilder temp = new StringBuilder();
for (int i = 0; i < baseName.Length; i++)
{
temp.Append(baseName[i]);
if (i != baseName.Length - 1)
{
temp.Append(",");
}
}
Write("public class " + name + " : " + temp + " ");
WriteCurlyBrackets();
BackToInsertContent();
}
public void WriteInterface(string name, params string[] baseName)
{
StringBuilder temp = new StringBuilder();
for (int i = 0; i < baseName.Length; i++)
{
temp.Append(baseName[i]);
if (i != baseName.Length - 1)
{
temp.Append(",");
}
}
Write("public interface " + name + " : " + temp + " ", true);
WriteCurlyBrackets();
BackToInsertContent();
}
public void WriteFun(List<string> keyName, string name, string othes = "", params string[] paraName)
{
WriteFun(name, Public, keyName, othes, paraName);
}
public void WriteFun(string name, string publicState = "public", List<string> keyName = null, string othes = "", params string[] paraName)
{
StringBuilder keyTemp = new StringBuilder();
if (keyName != null)
{
for (int i = 0; i < keyName.Count; i++)
{
keyTemp.Append(keyName[i]);
if (i != keyName.Count - 1)
{
keyTemp.Append(" ");
}
}
}
StringBuilder temp = new StringBuilder();
temp.Append(publicState + " " + keyTemp + " " + name + "()");
if (paraName.Length > 0)
{
foreach (string s in paraName)
{
temp.Insert(temp.Length - 1, s + ",");
}
temp.Remove(temp.Length - 2, 1);
}
temp.Append(" ");
temp.Append(othes);
Write(temp.ToString());
WriteCurlyBrackets();
}
/// <summary>
/// 设置光标位置,到大括号内插入内容
/// </summary>
/// <param name="num"></param>
public void BackToInsertContent()
{
currentIndex -= _backNum;
}
/// <summary>
/// 设置光标位置,到结束大括号外
/// </summary>
/// <param name="num"></param>
public void ToContentEnd()
{
currentIndex += _backNum;
}
public override string ToString()
{
return _stringBuilder.ToString();
}
}
}
5、Config
namespace XANTools.Editor
{
/// <summary>
/// 路径配置,根据自己实际路径进行配置
/// </summary>
public class PathConfig
{
public static readonly string NAMESPACE_DATA_ROOT_PATH = "Assets/AutoAddNamespace/Editor/Cache/";
public static readonly string NAMESPACE_DATA_ASSET_PATH = NAMESPACE_DATA_ROOT_PATH+"Data.asset";
}
public class NamespaceConfig {
public static readonly string DEFAULT_NAMESPACE_NAME = "Game";
}
}
?
|