Unity 工具 之 实现简单的添加脚本命名空间 Namespace 的小工具(不改动原始脚本模板)

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";
    }
}

猜你喜欢

转载自blog.csdn.net/u014361280/article/details/120451930
今日推荐