Unity脚本模板自定义字符串替换

来源:互联网 发布:网络电子老虎机技巧 编辑:程序博客网 时间:2024/05/18 06:29


在用Unity开发游戏的时候,由于经常要用到不同的脚本模板,特别是在写Editor和AttributeDrawer这类脚本时很想能实现一定规则的字符串替换,所以就写了这么个脚本实现自定义模板+自定义字符串替换的功能。

脚本内容主要分为五部分:

        Action:新建脚本时调用的内容

        ReplaceKeyword:对新建脚本中的字符串进行替换

        InvokeWhileCreateScript:新建脚本时调用的内容(主动调用)

        CreateTemplateLoader:根据自定义模板创建菜单

        FileIO:一些文件操作

一般这些内容是应该分开几个脚本写的,但为了“携带方便”,就把它们全都写在一起了


using UnityEditor;using UnityEngine;using System.IO;using System.Text.RegularExpressions;namespace UnityEditor.ProjectWindowCallback{public class UserDefinedScriptAction : UnityEditor.ProjectWindowCallback.EndNameEditAction{static readonly string TemplatesDir = EditorApplication.applicationContentsPath + "/Resources/ScriptTemplates/MyTemplates/";#region Actionpublic override void Action(int instanceId, string pathName, string resourceFile){//创建资源Object obj = CreateAssetFormTemplate(pathName, resourceFile);//高亮显示该资源ProjectWindowUtil.ShowCreatedAsset(obj);}internal static Object CreateAssetFormTemplate(string pathName, string resourceFile) {//Debug.Log (pathName + "-" + resourceFile);//获取要创建资源的绝对路径string fullName = Path.GetFullPath(pathName);//读取本地模版文件StreamReader reader = new StreamReader(resourceFile);string template = reader.ReadToEnd();reader.Close();//获取资源的文件名string fileName = Path.GetFileNameWithoutExtension(pathName);string content = RepalceKeyword (template, fileName);//写入新文件 StreamWriter writer = new StreamWriter(fullName, false, System.Text.Encoding.UTF8);writer.Write(content);writer.Close();//刷新本地资源AssetDatabase.ImportAsset(pathName);AssetDatabase.Refresh();return AssetDatabase.LoadAssetAtPath<Object>(pathName);}#endregion#region RepalceKeywordconst string startEndTag = "@@";const char divChar = ':';static string RepalceKeyword(string template, string fileName){System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder (template);stringBuilder.Replace ("#ScriptName#", fileName);stringBuilder.Replace ("#CompanyName#", PlayerSettings.companyName);stringBuilder.Replace ("#ProductName#", PlayerSettings.productName);stringBuilder.Replace ("#CreateTime#", System.DateTime.Now.ToString ("G"));foreach (Match match in Regex.Matches (stringBuilder.ToString (), "#CreateTime@.*#")) {if (match.Success) {string matchValue = match.Value;//Debug.Log (matchValue);int CreateTimeLenght = "#CreateTime@".Length;string timeFormat = matchValue.Substring (CreateTimeLenght, matchValue.Length - CreateTimeLenght - 1);//Debug.Log (timeFormat);try{string timeStr = System.DateTime.Now.ToString (timeFormat);if(timeStr == timeFormat){Debug.LogErrorFormat ("The DateTimeFormatInfo error: {0} is not a DateTimeFormat!", timeFormat);}else{stringBuilder.Replace (matchValue, timeStr);}}catch(System.FormatException e) {Debug.LogErrorFormat ("The DateTimeFormatInfo error: {0} is not a DateTimeFormat!", timeFormat);}}}if (fileName.EndsWith ("Editor")) {stringBuilder.Replace ("#EditorType#", fileName.Substring (0, fileName.Length - "Editor".Length));} else if (fileName.EndsWith ("AttributeDrawer")) {stringBuilder.Replace ("#AttributeType#", fileName.Substring (0, fileName.Length - "Drawer".Length));}//读取本地常量设置string iniFile = TemplatesDir + "TemplateConstant.ini";if (File.Exists (iniFile)) {StreamReader reader = new StreamReader(iniFile);string constantStrings = reader.ReadToEnd();reader.Close();if (constantStrings != null && constantStrings != "") {int startIndex = 0;int endIndex = 0;int strLen = constantStrings.Length;int tagLen = startEndTag.Length;while (endIndex < strLen) {startIndex = constantStrings.IndexOf (startEndTag, endIndex) + tagLen;if (startIndex >= 0) {endIndex = constantStrings.IndexOf (startEndTag, startIndex);if (endIndex >= 0) {string oneConst = constantStrings.Substring (startIndex, endIndex - startIndex);if (oneConst != "") {int divIndex = oneConst.IndexOf (divChar);if (divIndex >= 0) {string regionStr = oneConst.Substring (0, divIndex);string replaceStr = oneConst.Substring (divIndex + 1, oneConst.Length - divIndex - 1);stringBuilder.Replace (regionStr, replaceStr);endIndex += tagLen;startIndex = endIndex;continue;}}}}break;}}}return stringBuilder.ToString ();}#endregion#region InvokeWhileCreateScriptconst string UserTemplateDir = "/Resources/ScriptTemplates/MyTemplates/";static string GetSelectedPath(){string selectedPath = "Assets";//获取选中的资源Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);//遍历选中的资源以返回路径foreach (Object obj in selection){selectedPath = AssetDatabase.GetAssetPath(obj);if (!string.IsNullOrEmpty(selectedPath) && File.Exists(selectedPath)){selectedPath = Path.GetDirectoryName(selectedPath);break;}}return selectedPath;}/// <summary>/// 创建自定义脚本时调用的处理函数/// </summary>/// <param name="newScriptName">New script name.</param>/// <param name="templateFileName">Template file name.</param>public static void CreateScript(string newScriptName, string templateFileName){ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0,ScriptableObject.CreateInstance<UserDefinedScriptAction>(),UserDefinedScriptAction.GetSelectedPath() + "/" + newScriptName, null, EditorApplication.applicationContentsPath + UserTemplateDir + templateFileName);}#endregion#region CreateTemplateLoader[MenuItem("Assets/Create/TemplatesLoader.cs", false, 85)]static void LoadTemplates(){string templateOfLoader = @"namespace UnityEditor.ProjectWindowCallback{public class ScriptTemplatesLoader : UnityEngine.ScriptableObject{#NewMenuItem#}}";string oneMenuItem = @"[MenuItem(""Assets/Create UserDefined/{0}"", false, {1})]static void CreateScriptInstance_{2}(){{UserDefinedScriptAction.CreateScript (""{3}"", ""{4}"");}}#NewMenuItem#";string menuTag = "#NewMenuItem#";System.Text.StringBuilder templatesLoader = new System.Text.StringBuilder (templateOfLoader);string[] filesPath = Directory.GetFiles (TemplatesDir, "*.txt", SearchOption.AllDirectories);int filesLen = filesPath.Length;for (int i = 0; i < filesLen; i++) {filesPath [i] = Path.GetFileNameWithoutExtension (filesPath [i]);string[] fileDiv = filesPath [i].Split ('-');int divLen = fileDiv.Length;if (divLen == 3) {templatesLoader.Replace (menuTag, string.Format (oneMenuItem, fileDiv [1].Replace ("__", "/"), fileDiv [0], i, fileDiv [2], filesPath [i] + ".txt"));}}templatesLoader.Replace (menuTag, "");string saveDir = "Assets/Editor/ScriptTemplates/";string savePath = saveDir + "ScriptTemplatesLoader.cs";UserDefinedScriptAction.CheckAndCreateDirectory (saveDir);UserDefinedScriptAction.CreateFile (savePath, templatesLoader.ToString ());AssetDatabase.ImportAsset(savePath);AssetDatabase.Refresh();}#endregion#region FileIO/// <summary>/// 创建文件,并写入数据/// 不管原来文件是否存在/// </summary>/// <param name="filePath">File path.</param>/// <param name="content">Content.</param>static void CreateFile(string filePath, string content = ""){FileStream fs = new FileStream (filePath, FileMode.Create, FileAccess.Write);fs.Write (System.Text.Encoding.Default.GetBytes (content), 0, content.Length);fs.Close ();}/// <summary>/// 为了创建filePath,检查沿路的文件夹是否存在,如果不存在则创建/// </summary>/// <returns><c>true</c>, 如果文件存在, <c>false</c> otherwise.</returns>/// <param name="filePath">File path.</param>static bool CheckAndCreateDirectory(string filePath){if (File.Exists (filePath)) {return true;}string[] dirs = filePath.Split ('/');int len = dirs.Length - 1;string curDir = "";for (int i = 0; i < len; i++) {curDir += dirs [i] + "/";if (!Directory.Exists (curDir)) {Directory.CreateDirectory (curDir);}}return false;}#endregion}}

实际上,我只是想把自己写的第一个小插件给别人用一下,同时尝试一下在网上分享一下,所以更多地是想打包成一个包供大家下载。

百度云下载链接:https://pan.baidu.com/s/1i5j0PE1

以下是插件的使用说明:

使用说明:
1.插件详细说明
(1)Unity脚本模板知识:
     >>> Unity的脚本模板放在Editor\Data\Resources\ScriptTemplates\目录下
     >>> 模板文件名格式为
         菜单order-(相对Assets/Create/路径的)菜单路径(以"__"代替"/",如果以" _#A"这样的字符串结束还可以给菜单添加快捷键,关于快捷键可见附录二)-新建脚本默认名.脚本后缀.txt
     >>> 模板内容中的字符串"#SCRIPTNAME#"会在新建脚本的时候替换成新建脚本名
(2)此插件的作用:
     >>> 这个插件被编写的原因是感觉Unity的脚本模板字符串替换功能太少,所以编写插件新增了自定义字符串替换的功能
(3)自定义模板的规则说明:
     >>> 脚本模板的文件放在Unity的Editor\Data\Resources\ScriptTemplates\MyTemplates\目录下
     >>> 脚本模板的文件名称格式和Unity的相同
     >>> 默认可替换字符串:
         #ScriptName# => 文件名
         #CompanyName# => PlayerSettings里设置的公司名
         #ProductName# => PlayerSettings里设置的公司名
         #CreateTime# => 脚本创建时间
         #CreateTime@xx# => 带格式字符串的脚本创建时间,详情见附录一
         #EditorType# => 当新建的脚本名以Editor为后缀时,此字符串会被替换成 脚本名去掉后缀Editor
         #AttributeType# => 当新建的脚本名以AttributeDrawer为后缀时,此字符串会被替换成 脚本名去掉后缀Drawer
     >>> 自定义替换字符串:
         在目录Editor\Data\Resources\ScriptTemplates\MyTemplates\下创建配置文件TemplateConstant.ini
         以 "@@被替换字符串:替换字符串(可包含除了"@@"的任意字符串)@@" 的格式添加进文件里面即可


2.插件使用步骤:
(1)解压文件,将文件夹MyTemplates复制到Unity安装目录下的Editor\Data\Resources\ScriptTemplates\目录下
(2)打开Unity的工程,导入CreateTemplateScriptAction.unitypackage。
(3)点击菜单Assets/Create/TemplatesLoader.cs
     此时会新建一个脚本(不用在意,除非你想研究一下),并会看到新增了菜单Assets/Create UserDefined/xxxxxx(如果没有表明没有在本地新建脚本的模板),点击其中的菜单即可根据对应的模板创建脚本
(4)如果更新了模板,重复步骤三即可


附录一:
  创建时间格式:
///  #CreateTime@D# => Saturday, April 15, 2017
///  #CreateTime@hh:mm:ss tt zz# => 02:04:32 PM +08
///  #CreateTime@hh:mm:ss t z# => 02:04:32 P +8
///  #CreateTime@yyyy-M-d dddd# => 2017-4-15 Saturday
///  #CreateTime@yy-MMM-dd ddd# => 17-Apr-15 Sat
///  #CreateTime@yyyy MMMMM dd# => 2017 April 15
///  #CreateTime@yy-MM-dd# => 17-04-15
///  #CreateTime@Y# => April, 2017
///  #CreateTime@u# => 2017-04-15 14:04:33Z
///  #CreateTime@U# => Saturday, April 15, 2017 6:04:33 AM
///  #CreateTime@HH:mm:ss tt zz# => 14:04:33 PM +08
///  #CreateTime@t# => 2:04 PM
///  #CreateTime@s# => 2017-04-15T14:04:33
///  #CreateTime@R# => Sat, 15 Apr 2017 14:04:33 GMT
///  #CreateTime@O# => 2017-04-15T14:04:33.3649672+08:00
///  #CreateTime@M# => April 15
///  #CreateTime@g# => 4/15/2017 2:04 PM
///  #CreateTime@G# => 4/15/2017 2:04:33 PM
///  #CreateTime@f# => Saturday, April 15, 2017 2:04 PM
///  #CreateTime@F# => Saturday, April 15, 2017 2:04:33 PM
///  #CreateTime@d# => 4/15/2017
///  #CreateTime@T# => 2:04:33 PM
///  #CreateTime@HH:m:s tt zz# => 14:4:33 PM +08


附录二:
  某些快捷键:
% = ctrl
# = Shift
& = Alt
LEFT/RIGHT/UP/DOWN = 上下左右
F1…F2 = F...
HOME, END, PGUP, PGDN = 键盘上的特殊功能键


百度云下载链接:https://pan.baidu.com/s/1i5j0PE1

1 0
原创粉丝点击