Como personalizo o script gerado automaticamente?

11

Quando você cria um script por meio do editor do Unity, ele gera um script com algum código pré-formatado.

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 () {

    }
}

Quando crio um script, geralmente sou garantido o uso de código adicional, como um espaço para nome ou um editor personalizado. Além disso, quase sempre excluo o conteúdo do script gerado automaticamente. Existe uma maneira de alterar o código automático gerado pelo Unity?

Gnemlock
fonte
1
Eu nunca pensei em fazer isso. Obrigado por perguntar! Agora, para combinar as duas respostas para ter um modelo e analisá-lo para inserir informações extras, como espaço para nome ...
Draco18s não confia mais no SE

Respostas:

4

Além disso, você também pode

  1. Adicione um script de editor na pasta Assets / Editor que assine OnWillCreateAssetonde você pode analisar a saída e modificá-la. Por exemplo, um script que inserisse automaticamente um espaço para nome poderia se parecer com o seguinte:

    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. Insira seqüências de controle próprias nos modelos para facilitar a substituição OnWillCreateAsset, por exemplo

    finalCode = finalCode.Replace(@"#date#", DateTime.Now);
  3. Adicione mais modelos à pasta de modelos, por exemplo, um para o padrão Singleton - o Unity não se limita ao modelo de script único.

  4. Os trechos de código do visual studio são uma maneira de personalizar a criação de novos scripts (... e ainda mais - novas partes de script). Por exemplo, um trecho de código para particular SerializeFieldpode ser útil. Após a importação 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>
    

    em Ferramentas / Gerenciador de trechos de código / Meus trechos de código, basta digitar a guia dupla "pf" e digitar o nome do campo. Por exemplo:

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

    Ainda mais conveniente seriam trechos para sequências mais longas, muitas vezes repetidas, por exemplo, propriedade readonly apoiada por SerializeFieldcampo.

  5. O Visual studio também oferece uma ferramenta de geração de código muito poderosa, os Modelos de Texto T4 (a EF está usando o T4), embora eu pessoalmente ache duvidoso o uso prático para projetos do Unity - eles são um exagero, bastante complicado e a compilação do projeto provavelmente se tornará dependente do Visual Estúdio.

wondra
fonte
Isso funcionou como um encanto! Adicionei namespaces relevantes para usuários futuros. Eu também tive mais um problema, embora eu ache que possa ser único para mim; Eu não posso usar Path.GetFileWithoutExtension. Ele me diz que está tentando acessar um MonoBehaviour, o que parece estranho. Eu incluo o espaço para nome using Path = System.IO.Path.GetFileWithoutExtensione perco Pathtodos juntos. No final, eu tive que ignorar completamente a linha em si ( .Contains("class " + System.IO.Path.GetFileNameWithoutExtension(assetPath)));).
Gnemlock
Qual é a maneira mais simples de garantir que os arquivos sejam criados com LF e UTF-8 em vez de CRLF e UTF-8 com BOM?
Aaron Franke
@AaronFranke bem ... isso é uma solicitação bastante específica. Eu tentaria perguntar no stackoverflow.com como criar string/ File.Writeproduzir somente LF com BOM. Tanto quanto sei '\ n' deve ser apenas LF, você também pode tentar, Environment.Newlinemas deve ser CRLF. Também pode haver uma opção para usar ganchos git se tudo mais falhar. A lista técnica deve ser fácil com esta pergunta sobre o fluxo de pilha .
Wondra
15

Você pode encontrar os modelos de script para gerar automaticamente o código na sua pasta de instalação do Unity. Eu encontro os modelos em "Unity / Editor / Data / Resources / ScriptTemplates" , enquanto outras fontes o encontraram em "Unity / Editor / Data / Resources" .

Os modelos genéricos de UnityScript e C # são identificados como os arquivos "82-Javascript-NewBehaviourScript.js.txt" e "81-C # Script-NewBehaviourScript.cs.txt" , respectivamente. Você pode editar diretamente esses arquivos para alterar a maneira como o Unity gera automaticamente o script.

Você também pode incluir modelos adicionais, que aparecerão quando você selecionar "Criar" na janela "Projeto" . Os modelos não parecem exigir numeração exclusiva e usam a sequência inicial para determinar a hierarquia do menu, onde "__" indica um submenu. Por exemplo, ter um arquivo chamado "81-C # Script__Editor Script-NewBehaviourScript.cs.txt" fornecerá um menu adicional " C # Script" , com a subopção para criar um "Script do editor" usando este modelo.

Você não renomear os modelos originais; estes são usados ​​mais diretamente, pelo mecanismo. Por exemplo, renomear "81-C # Script-NewBehaviourScript.cs.txt" impedirá que você adicione novos scripts C # como componentes, diretamente através do inspetor.


Abaixo está o meu próprio exemplo, embora ele demonstre práticas específicas às quais sou mais personalizado. Por exemplo, eu prefiro ter meu script de editor personalizado no mesmo arquivo que a classe de destino, então o encapsulo em #if UNITY_EDITOR .. #endifvez de colocá-lo em uma pasta de editor genérica "não compile na compilação".

Não tenho certeza se é possível fornecer o contexto de um espaço para nome personalizado; Eu simplesmente uso "NAMESPACE", pois isso permite que eu forneça o pós-criação correto do namespace, usando a função "find..replace all" comumente embutida.


O modelo:

/* 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
}

A saída:

/* 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
fonte