Unity扩展脚本模板(以Lua为例)
简介
在项目中开发中,经常会创建大量的脚本类的文件,比如使用Lua时,需要创建新的Lua脚本,学习或使用Shader时也会创建一些新的Shader文件,对于这些文件如果从头开始写将会是一个痛苦的事情,而且多数内容是重复的。在使用很多其它工具时,其都提供或者可以自定义一些标准的模板,根据模板创建出含有基础内容的脚本文件,然后在其基础上进行修改即可。
其实Unity也提供了一些标准的模板,可以帮助我们创建新的文件,比如可以在Project面板右键或者通过Assets/Create菜单中创建Shader、C#脚本等,当创建完后可以修改文件名称,名称修改完成后文件内容对应的内容也被修改。
本文将重点以Lua脚本为例来解释如何扩展代码模板
声明
本文中的内容属于个人总结整理而来,个人水平有限,对于部分细节难免有理解错误及遗漏之处,如果您在阅读过程中有所发现,希望您能指正,同时文章中的部分内容也参考了其它大神的文章,如果文章中的内容侵犯了您的权益,表示非常歉意,请您指出,我将尽快修改。
如果您进行转载,请标明出处。
Unity技术 扩展脚本模板(Lua为例)(http://www.liyubin.com/articles/2019/04/18/1555574809340.html)
扩展脚本模板
Unity中自带的模板
Unity默认带有一部分模板,这些模板位置Unity的安装目录XXX\Editor\Data\Resources\ScriptTemplates中
目录中存在的txt文件即是Unity提供的内置模板,通过文件名称可以简单了解到其作用,不过此处特别指出文件名开始的数字,如:81,83等,其序列代表了Unity对于此模板在创建时所在菜单中的排序,请不要认识,只是对模板文件添加数字即可就可以控制排序了,Unity是通过MenuItem提供的序列来决定排序的。
Unity自带模板内容
使用文件编辑器打开对应的文件,比如打开81的创建C#脚本的模板文件,
认真查看一下模板的内容,就会觉得这内容太熟悉了,这就是生成C#脚本的模板内容,如果自己对于此模板内容不满意的话,可以自己修改的。
对于内容中存在着类似于宏的字符,比如:#SCRIPTNAME#,#NOTRIM#等,后面在实际操作时,会详细的看到作用
Unity引擎模板使用方式
由于Unity并未提供相应的说明来介绍如何自定义脚本模板,其文档中也没有对应部分的描述,所以需要从Unity的源码中查看这部分的内容,Unity引擎开发组对引擎的C#部分的代码在GitHub-UnityCsReference上进行了开源(如果不清楚什么是GitHub的话,请反思一下自己的学习方式及程序功底),将其下载到本地,接下来我们将详细查看一下Unity是如何对模板进行操作的。
查看脚本NewScriptDropdownItem.CreateScript可以看到Unity使用创建C#的模板进行脚本的创建,
接下来重点查看ProjectWindowUtil可以看到大量的可供参考的内容,其中重要的一个是EndNameEditAction类,ProjectWindowUtil.StartNameEditingIfProjectWindowExists方法的实现。
-
EndNameEditAction类
当文件创建完成后,会回调EndNameEditorAction中的方法,主要的方法为:
public abstract void Action(int instanceId, string pathName, string resourceFile);pathName修改名称后的文件路径,resourceFile使用的模板文件路径 -
ProjectWindowUtil.StartNameEditingIfProjectWindowExists方法
此方法:
public static void StartNameEditingIfProjectWindowExists(int instanceID, EndNameEditAction endAction, string pathName, Texture2D icon, string resourceFile),其中endAction创建完成后需要调用的EndNameAction,pathName是指需要创建的文件的位置,icon是指文件的图标,resourceFile为模板文件路径
扩展Lua脚本的模板
-
创建Lua脚本模板
提前编辑好Lua脚本:
#NAME# = Class(function(self) end) function #NAME#:DoAwake() end function #NAME#:DoEnable() end function #NAME#:DoStart() end function #NAME#:DoDisable() end function #NAME#:DoDestroy() end
PS:具体的内容根据自己的需求定义,并将其命名为82-Lua-NewLuaScript.txt,加入到项目中,后续将需要指定所在的位置
-
创建辅助类-PathUtil
主要提供对路径的操作,其中:
PathUtil.GetAssetPath:将绝对路径进行查找替换为相对于Unity项目Assets目录的路径
PathUtil.GetDiskPath:将相对于Assets的路径查的替换为绝对路径
PathUtil.GetSelectionAssetDirPath:查找选中的目录,如果选中的是文件则会将其所在的目录返回具体实现:
public static class PathUtil { public static string GetAssetPath(string dirPath) { dirPath = dirPath.Replace("\\", "/"); if (dirPath.StartsWith(Application.dataPath)) { return "Assets" + dirPath.Replace(Application.dataPath, ""); } return string.Empty; } public static string GetDiskPath(string assetPath) { if (string.IsNullOrEmpty(assetPath)) { return string.Empty; } assetPath = assetPath.Replace("\\", "/"); if (!assetPath.StartsWith("Assets")) { return string.Empty; } return Application.dataPath + assetPath.Substring(assetPath.IndexOf("Assets") + 6); } public static string GetSelectionAssetDirPath() { string path = "Assets"; foreach (UnityEngine.Object obj in Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets)) { if(obj == null) { continue; } path = AssetDatabase.GetAssetPath(obj); if(Path.HasExtension(path)) { path = Path.GetDirectoryName(path); } break; } return path; } }
-
创建CreateLuaScriptAction类,继承EndNameEditAction类
用于侦听创建文件成功后回调,文件创建成功后,根据提供的文件位置及模板,对文件模板中的类似于宏定义的文件进行替换为实际的意义
具体实现:
internal class CreateLuaScriptAction : EndNameEditAction { public override void Action(int instanceId, string pathName, string resourceFile) { string content = File.ReadAllText(PathUtil.GetDiskPath(resourceFile)); string fileName = Path.GetFileNameWithoutExtension(pathName); content = content.Replace("#NAME#", fileName); string fullName = PathUtil.GetDiskPath(pathName); File.WriteAllText(fullName, content); AssetDatabase.ImportAsset(pathName); Object obj = AssetDatabase.LoadAssetAtPath(pathName, typeof(UnityEngine.Object)); ProjectWindowUtil.ShowCreatedAsset(obj); } }
-
添加操作菜单
LuaScriptCreater类,提供一个用于创建Lua脚本的菜单:
public static class LuaScriptCreater { private static readonly string LuaScriptIconPath = "Assets/Tools/ScriptTemplates/lua_icon64.png"; private static readonly string LuaScriptTemplatePath = "Assets/Tools/ScriptTemplates/82-Lua-NewLuaScript.txt"; [MenuItem("Assets/Create/Lua Script", false, 82)] private static void CreateLuaScript() { if (EditorApplication.isCompiling || EditorApplication.isPlaying) { EditorUtility.DisplayDialog("警告", "无法在游戏运行时或代码编译时创建lua脚本", "确定"); return; } Texture2D icon = AssetDatabase.LoadAssetAtPath<Texture2D>(LuaScriptIconPath); string scriptDirPath = PathUtil.GetSelectionAssetDirPath(); ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<CreateLuaScriptAction>(), scriptDirPath + "/NewLuaScript.txt", icon, LuaScriptTemplatePath); } }