Unity杂文——自定义创建模板脚本

原文地址

前言

相信大多数Unity开发人员在创建脚本的时候,经常会修改自从生成的脚本内容,比如去掉继承的MonoBehavior,添加命名空间,或者继承固定的接口、类等。这样重复的工作看似花费不了多少时间,但是如果每次创建都需要修改,还是有点麻烦的,所以如果我们能按照我们自定一的模板脚本去创建脚本就可以了。

问题

笔者在团队开发中发现,每次创建UI的脚本的时候都需要固定修改继承,和添加一些标签等,这些重复性的工作笔者想了想可不可按照自定义的模板创建脚本。笔者发现unity自带的在unity安装目录下创建模板脚本有很大的缺点,只能创建C#脚本,并且只可以自己使用,并不可以上传到项目的库进行团队使用,于是笔者参考网上的一些文章写了下面的解决方案。

解决方法

首先我们在创建一个Editor Default Resources目录,这个目录是提供为编辑器模式使用的资源路径,加载此目录的资源文件代码如下:
EditorGUIUtility.Load(filePath)
加载后通过as转换成需要的类型就可以了
笔者模板文件存放的目录如下:
---Assets
------Editor Default Resources
---------CustomScriptTemplate
------------C# Script-NewNoMonoBehaviourScript.text

模板文件的内容如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace #NAMESPACE#
{
    public class #SCRIPTNAME#
    {
        #region 字段

        

        #endregion
        
        #region 属性

        

        #endregion
        
        #region 方法
        
        
        
        #endregion
    }
}

在选中的目录里创建模板脚本

制作的原理就是通过读取模板文件的内容,然后将内容写入新的脚本中,监听编辑结束后替换新模板中的固定字符串就可以了。
直接上代码:

using System.Text;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEditor.ProjectWindowCallback;
using UnityEngine;

public static class CreatNewCShapScript
{
        /// <summary>
        /// 创建不继承MonoBehaviour脚本
        /// </summary>
        [MenuItem("Assets/Create/C# Scripts Menu/C# NoMonoBehaviourScript", false,81)]
        public static void CreatNoMonoBehaviourScript()
        {
            //参数为传递给CreateEventCSScriptAsset类action方法的参数
            ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0,
                ScriptableObject.CreateInstance<CreateNewCShapScriptAsset>(),
                GetSelectPathOrFallback() + "/NewNoMonoBehaviourScript.cs", null,
                "CustomScriptTemplate/C# Script-NewNoMonoBehaviourScript.txt");
        }

        /// <summary>
        /// 取得要创建文件的路径
        /// </summary>
        /// <returns></returns>
        public static string GetSelectPathOrFallback()
        {
            string path = "Assets";
            //遍历选中的资源以获得路径
            //Selection.GetFiltered是过滤选择文件或文件夹下的物体,assets表示只返回选择对象本身
            foreach (UnityEngine.Object obj in Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets))
            {
                path = AssetDatabase.GetAssetPath(obj);
                if (!string.IsNullOrEmpty(path) && File.Exists(path))
                {
                    path = Path.GetDirectoryName(path);
                    break;
                }
            }
            return path;
        }

        /// <summary>
        /// 创建脚本文件的委托类
        /// </summary>
        class CreateNewCShapScriptAsset : EndNameEditAction
        {
            public override void Action(int instanceId, string pathName, string resourceFile)
            {
                UnityEngine.Object obj = CreateScriptAssetFromTemplate(pathName, resourceFile);                         //创建资源
                ProjectWindowUtil.ShowCreatedAsset(obj);                                                                //高亮显示资源
            }
            
            internal static UnityEngine.Object CreateScriptAssetFromTemplate(string pathName, string resourceFile)
            {
                string fullPath = Path.GetFullPath(pathName);                                                           //获取要创建资源的绝对路径
                string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pathName);                           //获取文件名,不含扩展名
                var textAsset = EditorGUIUtility.Load(resourceFile) as TextAsset;
                string resourceFileText = textAsset.text;
                resourceFileText = Regex.Replace(resourceFileText, "#NAMESPACE#",
                    CompilationPipeline.GetAssemblyRootNamespaceFromScriptPath(pathName));
                resourceFileText = Regex.Replace(resourceFileText, "#SCRIPTNAME#", fileNameWithoutExtension);              //将模板类中的类名替换成你创建的文件名
                bool encoderShouldEmitUTF8Identifier = true;                                                            //参数指定是否提供 Unicode 字节顺序标记
                bool throwOnInvalidBytes = false;                                                                       //是否在检测到无效的编码时引发异常
                UTF8Encoding encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier, throwOnInvalidBytes);
                bool append = false;
                StreamWriter streamWriter = new StreamWriter(fullPath, append, encoding);                               //写入文件
                streamWriter.Write(resourceFileText);
                streamWriter.Close();
                AssetDatabase.ImportAsset(pathName);                                                                    //刷新资源管理器
                AssetDatabase.Refresh();
                return AssetDatabase.LoadAssetAtPath(pathName, typeof(UnityEngine.Object));
            }
        }
}

此代码有一个比较重要的一点就是获取文件所在的程序集的命名空间名字,因为要自动添加命名空间,最后找到了对应的API,通过CompilationPipeline.GetAssemblyRootNamespaceFromScriptPath(pathName)获取地址路径下的命名空间名字,然后动态替换就可以了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容