如何自定义自动生成的脚本?


11

通过Unity编辑器创建脚本时,它会生成带有一些预格式化代码的脚本。

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

public class GenericClass : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}

创建脚本时,通常可以保证使用其他代码,例如名称空间或自定义编辑器。此外,我几乎总是从自动生成的脚本中删除内容。有没有办法更改Unity生成的自动代码?


1
我什至从未考虑过这样做。感谢您的询问!现在将两个答案结合在一起以得到一个模板然后对其进行解析以插入其他信息,例如名称空间...
Draco18s不再信任SE的

Answers:


4

另外你也可以

  1. 在Assets / Editor文件夹中添加一个编辑器脚本,该脚本订阅OnWillCreateAsset您可以解析输出并对其进行修改的位置。例如,将自动插入名称空间的脚本如下所示:

    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text.RegularExpressions;
    
    using UnityEditor;
    
    public class InsertNS : UnityEditor.AssetModificationProcessor
    {
        public static void OnWillCreateAsset(string path)
        {
            string assetPath = Regex.Replace(path, @".meta$", string.Empty);
            if (!assetPath.EndsWith(".cs")) return;
    
            var code = File.ReadAllLines(assetPath).ToList();
            if (code.Any(line => line.Contains("namespace"))) return;//already added by IDE
    
            //insert namespace
            int idx = code.FindIndex(line => line
                .Contains("class " + Path.GetFileNameWithoutExtension(assetPath)));
            code.Insert(idx, Regex.Replace(
            assetPath.Replace('/','.'), @"^([\w+.]+)\.\w+\.cs$", "namespace $1 {\n"));
            code.Add("}");
    
            //correct indentation
            for (int i = idx + 1; i < code.Count - 1; i++) code[i] = '\t' + code[i];
    
            var finalCode = string.Join("\n", code.ToArray());
            File.WriteAllText(assetPath, finalCode);
            AssetDatabase.Refresh();
        }
    }
  2. 将自己的控制序列插入模板,以便于替换OnWillCreateAsset,例如

    finalCode = finalCode.Replace(@"#date#", DateTime.Now);
  3. 将更多模板添加到模板文件夹,例如,一个用于Singleton模式的模板-Unity不限于单个脚本模板。

  4. Visual Studio 代码段是自定义创建新脚本(甚至更进一步-新脚本部分)的方法。例如,专用的代码段SerializeField可能会派上用场。导入后privateField.snippet

    <?xml version="1.0" encoding="utf-8"?>
    <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
      <CodeSnippet Format="1.0.0">
        <Header>
          <Title>
            Serialized private field
          </Title>
          <Author>Myself</Author>
          <Description>Adds private serializable field visible to Unity editor</Description>
          <Shortcut>pf</Shortcut>
        </Header>
        <Snippet>
          <Imports>
            <Import>
              <Namespace>UnityEngine</Namespace>
            </Import>
          </Imports>
          <Declarations>
            <Literal>
              <ID>FieldName</ID>
              <ToolTip>Replace with field name.</ToolTip>
              <Default>myField</Default>
            </Literal>
          </Declarations>
          <Code Language="CSharp">
            <![CDATA[[SerializeField] float _$FieldName$;]]>
          </Code>
        </Snippet>
      </CodeSnippet>
    </CodeSnippets>

    进入“ 工具/代码段管理器” /“我的代码段”,您只需输入“ pf”双标签并输入字段名称即可。例如:

    //"pf" tab tab "speed" produces
    [SerializeField] float _speed;

    对于经常重复的较长序列(例如,由SerializeField字段支持的只读属性)的摘要,将更加方便。

  5. Visual Studio还提供了非常强大的代码生成工具T4文本模板(EF正在使用T4),尽管我个人发现Unity项目的实际用途令人怀疑-它们过大,相当复杂,并且项目的编译可能会依赖Visual工作室。


这就像一个魅力!我为将来的用户添加了相关的名称空间。我还遇到了另一个问题,尽管我认为这可能对我来说是唯一的。我不能使用Path.GetFileWithoutExtension。它告诉我它正在尝试访问MonoBehaviour,这似乎很奇怪。我包含了命名空间using Path = System.IO.Path.GetFileWithoutExtension,而我Path全都失去了。最后,我不得不完全认清这条线本身(.Contains("class " + System.IO.Path.GetFileNameWithoutExtension(assetPath)));)。
Gnemlock

确保使用LF和UTF-8创建文件而不是使用BOM创建CRLF和UTF-8的最简单方法是什么?
亚伦·弗兰克

@AaronFranke好...多数民众赞成在具体的要求。我会尝试在stackoverflow.com上询问如何使用BOM 制作string/ File.Write仅输出LF。据我所知'\ n' 应该只是LF,您也可以尝试改Environment.Newline而应该是CRLF。如果其他所有操作失败,也可以选择使用git hooks。有了这个stackoverflow问题, BOM应该很容易。
温德拉

15

您可以在Unity安装文件夹中找到用于自动生成代码的脚本模板。我在“ Unity / Editor / Data / Resources / ScriptTemplates”下找到模板,而其他来源“ Unity / Editor / Data / Resources”下找到了模板。

通用UnityScript和C#模板分别标识为文件“ 82-Javascript-NewBehaviourScript.js.txt”“ 81-C#Script-NewBehaviourScript.cs.txt”。您可以直接编辑这些文件,以更改Unity自动生成脚本的方式。

您还可以包括其他模板,这些模板将在您从“项目”窗口中选择“创建”时出现。模板似乎不需要唯一编号,而是使用初始字符串来确定菜单层次结构,其中“ __”表示子菜单。例如,拥有一个名为“ 81-C#Script__Editor Script-NewBehaviourScript.cs.txt”的文件,将为您提供一个额外的“ C#Script”菜单,并带有使用该模板创建“ Editor Script”的子选项。

不要修改原有的模板; 这些由引擎直接使用。例如,重命名“ 81-C#Script-NewBehaviourScript.cs.txt”将阻止您直接通过检查器添加新的C#脚本作为组件。


下面是我自己的示例,尽管它演示了我最习惯的特定实践。例如,我更喜欢将自定义编辑器脚本与目标类放在同一文件中,因此我将其封装在中#if UNITY_EDITOR .. #endif,而不是将其放置在通用的“请勿在构建中编译”编辑器文件夹中。

我不确定是否有可能提供自定义名称空间的上下文。我只使用“ NAMESPACE”,因为这使我可以使用常用的“ find..replace all”功能提供正确的名称空间创建后的功能。


模板:

/* Created by Gnemlock */

using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace NAMESPACE
{
    public class #SCRIPTNAME# : MonoBehaviour 
    {
        /// <summary>This method will be called at the start of each frame where this 
        /// instance of <see cref="NAMESPACE.#SCRIPTNAME#"/> is enabled.</summary>
        void Update ()
        {
            #NOTRIM#
        }
    }
}

namespace NAMESPACE.UTILITY
{
    #if UNITY_EDITOR
    [CustomEditor(typeof(#SCRIPTNAME#))] public class #SCRIPTNAME#Editor : Editor
    {
        public override void OnInspectorGUI()
        {
            DrawDefaultInspector();

            #SCRIPTNAME# s#SCRIPTNAME# = target as #SCRIPTNAME#;
        }
    }
    #endif
}

输出:

/* Created by Gnemlock */

using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace MyNamespace
{

    public class UpdatedClass : MonoBehaviour 
    {
        /// <summary>This method will be called at the start of each frame where this 
        /// instance of <see cref="MyNamespace.UpdatedClass"/> is enabled.</summary>
        void Update ()
        {

        }
    }
}

namespace MyNamespace.UTILITY
{
    #if UNITY_EDITOR
    [CustomEditor(typeof(UpdatedClass))] public class UpdatedClassEditor : Editor
    {
        public override void OnInspectorGUI()
        {
            DrawDefaultInspector();

            UpdatedClass sUpdatedClass = target as UpdatedClass;
        }
    }
    #endif
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.