Unity扩展脚本模板(以Lua为例)

  |   0 评论   |   0 浏览

简介

在项目中开发中,经常会创建大量的脚本类的文件,比如使用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中

Unity Script Template

目录中存在的txt文件即是Unity提供的内置模板,通过文件名称可以简单了解到其作用,不过此处特别指出文件名开始的数字,如:81,83等,其序列代表了Unity对于此模板在创建时所在菜单中的排序,请不要认识,只是对模板文件添加数字即可就可以控制排序了,Unity是通过MenuItem提供的序列来决定排序的。

Unity自带模板内容

使用文件编辑器打开对应的文件,比如打开81的创建C#脚本的模板文件,

Unity CSharp Template

认真查看一下模板的内容,就会觉得这内容太熟悉了,这就是生成C#脚本的模板内容,如果自己对于此模板内容不满意的话,可以自己修改的。

对于内容中存在着类似于宏的字符,比如:#SCRIPTNAME#,#NOTRIM#等,后面在实际操作时,会详细的看到作用

Unity引擎模板使用方式

由于Unity并未提供相应的说明来介绍如何自定义脚本模板,其文档中也没有对应部分的描述,所以需要从Unity的源码中查看这部分的内容,Unity引擎开发组对引擎的C#部分的代码在GitHub-UnityCsReference上进行了开源(如果不清楚什么是GitHub的话,请反思一下自己的学习方式及程序功底),将其下载到本地,接下来我们将详细查看一下Unity是如何对模板进行操作的。

查看脚本NewScriptDropdownItem.CreateScript可以看到Unity使用创建C#的模板进行脚本的创建,

Unity Create CS

接下来重点查看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);
        }
    }
    

参考资料


标题:Unity扩展脚本模板(以Lua为例)
作者:liyubin
地址:http://www.liyubin.com/articles/2019/04/18/1555574809340.html