Как настроить автоматически сгенерированный скрипт?

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?

Gnemlock
источник
1
Я никогда даже не думал об этом. Спасибо за вопрос! Теперь, чтобы объединить два ответа, чтобы получить шаблон, а затем проанализировать его, чтобы вставить дополнительную информацию, например, пространство имен ...
Draco18s больше не доверяет SE

Ответы:

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;

    Еще более удобными были бы фрагменты для часто повторяющихся длинных последовательностей, например свойство readonly, поддерживаемое SerializeFieldполем.

  5. Visual Studio также предлагает очень мощный инструмент генерации кода, текстовые шаблоны T4 (EF использует T4), хотя я лично считаю сомнительным практическое использование проектов Unity - они излишни, довольно сложны, и компиляция проекта, вероятно, станет зависеть от Visual Студия.

wondra
источник
Это сработало как шарм! Я добавил соответствующие пространства имен для будущих пользователей. У меня также была еще одна проблема, хотя я думаю, что она может быть уникальной для меня; Я не могу использовать Path.GetFileWithoutExtension. Это говорит мне, что он пытается получить доступ к MonoBehaviour, что кажется странным. Я включаю пространство имен using Path = System.IO.Path.GetFileWithoutExtension, и я теряю Pathвсе вместе. В конце концов, мне пришлось полностью опередить саму линию ( .Contains("class " + System.IO.Path.GetFileNameWithoutExtension(assetPath)));).
Гнемлок
Какой самый простой способ убедиться, что файлы создаются с использованием LF и UTF-8, а не CRLF и UTF-8 с использованием спецификации?
Аарон Франке
@AaronFranke хорошо ... это довольно конкретный запрос. Я хотел бы попробовать спросить на stackoverflow.com, как сделать string/ File.Writeвывод LF-only с BOM. Насколько я знаю, '\ n' должно быть просто LF, вы можете попробовать Environment.Newlineвместо этого, но это должен быть CRLF. Также может быть возможность использовать git hooks, если все остальное не работает. С этим вопросом о стековом потоке должно быть легко .
Wondra
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» с дополнительной опцией для создания «Редактора сценария» с использованием этого шаблона.

Вы не переименовывайте оригинальные шаблоны; они используются более непосредственно двигателем. Например, переименование «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
}
Gnemlock
источник