Wie passe ich automatisch generierte Skripte an?

11

Wenn Sie ein Skript über den Unity-Editor erstellen, wird ein Skript mit vorformatiertem Code generiert.

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

    }
}

Wenn ich ein Skript erstelle, wird im Allgemeinen garantiert, dass ich zusätzlichen Code verwende, z. B. einen Namespace oder einen benutzerdefinierten Editor. Außerdem lösche ich fast immer Inhalte aus dem automatisch generierten Skript. Gibt es eine Möglichkeit, den von Unity generierten automatischen Code zu ändern?

Gnemlock
quelle
1
Ich habe noch nie darüber nachgedacht. Danke für die Frage! Kombinieren Sie nun die beiden Antworten, um eine Vorlage zu erhalten, und analysieren Sie sie dann, um zusätzliche Informationen wie den Namespace einzufügen ...
Draco18s vertraut SE

Antworten:

4

Darüber hinaus können Sie auch

  1. Fügen Sie im Ordner "Assets / Editor" ein Editor-Skript hinzu, das abonniert, OnWillCreateAssetwo Sie die Ausgabe analysieren und ändern können. Ein Skript, das automatisch einen Namespace einfügt, könnte beispielsweise folgendermaßen aussehen:

    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. Fügen Sie eigene Steuersequenzen in Vorlagen ein, um sie einfach zu ersetzen OnWillCreateAsset, z

    finalCode = finalCode.Replace(@"#date#", DateTime.Now);
  3. Fügen Sie dem Vorlagenordner weitere Vorlagen hinzu, z. B. eine für das Singleton-Muster. Unity ist nicht auf einzelne Skriptvorlagen beschränkt.

  4. Mit den Visual Studio- Codefragmenten können Sie das Erstellen neuer Skripte anpassen (... und noch weiter - neue Skriptteile). Zum Beispiel könnte ein Code-Snippet für private SerializeFieldnützlich sein. Nach dem Import 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>

    Unter Extras / Code-Snippet-Manager / Meine Code-Snippets können Sie einfach die doppelte Registerkarte "pf" eingeben und den Namen des Felds eingeben . Z.B:

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

    Noch praktischer wären Schnipsel für häufig wiederholte längere Sequenzen, z. B. schreibgeschützte Eigenschaften, die von unterstützt werden SerializeField Feld .

  5. Visual Studio bietet auch ein sehr leistungsfähiges Tool zur Codegenerierung, die T4-Textvorlagen (EF verwendet T4), obwohl ich persönlich die praktische Verwendung für Unity-Projekte zweifelhaft finde - sie sind übertrieben, ziemlich kompliziert und die Kompilierung von Projekten würde wahrscheinlich von Visual abhängen Studio.

wondra
quelle
Das hat wie ein Zauber gewirkt! Ich habe relevante Namespaces für zukünftige Benutzer hinzugefügt. Ich hatte noch ein Problem, obwohl ich denke, dass es eines sein könnte, das für mich einzigartig ist. Ich kann nicht verwenden Path.GetFileWithoutExtension. Es sagt mir, dass es versucht , auf ein zuzugreifen MonoBehaviour, was seltsam erscheint. Ich füge den Namespace hinzu using Path = System.IO.Path.GetFileWithoutExtensionund verliere Pathalles zusammen. Am Ende musste ich die Linie selbst vollständig flügge machen ( .Contains("class " + System.IO.Path.GetFileNameWithoutExtension(assetPath)));).
Gnemlock
Was ist der einfachste Weg, um sicherzustellen, dass Dateien mit LF und UTF-8 anstatt mit CRLF und UTF-8 mit Stückliste erstellt werden?
Aaron Franke
@ AaronFranke gut ... das ist eine ziemlich spezifische Anfrage. Ich würde versuchen, auf stackoverflow.com zu fragen, wie LF-only mit Stückliste erstellt string/ File.Writeausgegeben werden soll. Soweit ich weiß , ‚\ n‘ sollte nur LF sein, können Sie auch versuchen , Environment.Newlinestattdessen aber es sollte CRLF sein. Es kann auch eine Option zur Verwendung von Git-Hooks geben, wenn alles andere fehlschlägt. Die Stückliste sollte mit dieser Frage zum Stapelüberlauf einfach sein .
Wondra
15

Die Skriptvorlagen zum automatischen Generieren von Code finden Sie in Ihrem Unity-Installationsordner. Ich finde die Vorlagen unter "Unity / Editor / Daten / Ressourcen / ScriptTemplates" , während andere Quellen sie unter "Unity / Editor / Daten / Ressourcen" gefunden haben .

Die generischen UnityScript- und C # -Vorlagen werden als die Dateien "82-Javascript-NewBehaviourScript.js.txt" und "81-C # Script-NewBehaviourScript.cs.txt" identifiziert . Sie können diese Dateien direkt bearbeiten, um die Art und Weise zu ändern, in der Unity automatisch Skripte generiert.

Sie können auch zusätzliche Vorlagen, die angezeigt wird , wenn Sie wählen „Create“ aus dem „Projekt“ Fenster. Vorlagen scheinen keine eindeutige Nummerierung zu erfordern und bestimmen anhand der Anfangszeichenfolge die Menühierarchie, wobei "__" ein Untermenü bezeichnet. Wenn Sie beispielsweise eine Datei mit dem Namen "81-C # Script__Editor Script-NewBehaviourScript.cs.txt" haben, erhalten Sie ein zusätzliches " C # Script" -Menü mit der Unteroption zum Erstellen eines dieser Vorlage "Editor-Skript" .

Haben nicht die Originalvorlagen umbenennen; Diese werden direkter vom Motor verwendet. Wenn Sie beispielsweise "81-C # Script-NewBehaviourScript.cs.txt" umbenennen , können Sie keine neuen C # -Skripte als Komponenten direkt über den Inspektor hinzufügen.


Unten ist mein eigenes Beispiel, obwohl es bestimmte Praktiken zeigt, an die ich am meisten gewöhnt bin. Zum Beispiel möchte ich mein benutzerdefiniertes Editor-Skript lieber in derselben Datei wie die Zielklasse haben, also kapsle ich es ein #if UNITY_EDITOR .. #endif, anstatt es in einem generischen Editorordner "Nicht in Build kompilieren" abzulegen.

Ich bin nicht sicher, ob es überhaupt möglich ist, den Kontext eines benutzerdefinierten Namespace anzugeben. Ich verwende einfach "NAMESPACE", da dies mir ermöglicht, den korrekten Namespace nach der Erstellung mithilfe der allgemein integrierten Funktion "find..replace all" bereitzustellen.


Die Vorlage:

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

Die Ausgabe:

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