Jak dostosować automatycznie generowany skrypt?

11

Kiedy tworzysz skrypt za pomocą edytora Unity, generuje skrypt z pewnym wstępnie sformatowanym kodem.

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

    }
}

Podczas tworzenia skryptu generalnie gwarantuje się użycie dodatkowego kodu, takiego jak przestrzeń nazw lub edytor niestandardowy. Co więcej, prawie zawsze usuwam zawartość z automatycznie generowanego skryptu. Czy istnieje sposób na zmianę automatycznego kodu generowanego przez Unity?

Gnemlock
źródło
1
Nigdy nawet nie pomyślałem o zrobieniu tego. Dzięki, że pytasz! Teraz połącz dwie odpowiedzi, aby utworzyć szablon, a następnie przeanalizuj go, aby wstawić dodatkowe informacje, takie jak przestrzeń nazw ...
Draco18s nie ufa już

Odpowiedzi:

4

Ponadto możesz również

  1. Dodaj skrypt edytora w folderze Assets / Editor, który subskrybuje miejsce, w OnWillCreateAssetktórym możesz analizować dane wyjściowe i modyfikować je. Na przykład skrypt, który automatycznie wstawi przestrzeń nazw, może wyglądać następująco:

    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. Wstaw własne sekwencje kontrolne do szablonów, aby łatwo je wymienić OnWillCreateAsset, np

    finalCode = finalCode.Replace(@"#date#", DateTime.Now);
  3. Dodaj więcej szablonów do folderu szablonów, na przykład jeden dla wzoru Singleton - Unity nie ogranicza się do jednego szablonu skryptu.

  4. Fragmenty kodu studia wizualnego są sposobem na dostosowanie tworzenia nowych skryptów (... a nawet - nowych części skryptu). Na przykład SerializeFieldprzydatny może być fragment kodu dla prywatnego . Po zaimportowaniu 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>

    w Narzędzia / Menedżer fragmentów kodu / Moje fragmenty kodu wystarczy wpisać podwójną kartę „pf” i wpisać nazwę pola. Na przykład:

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

    Jeszcze wygodniejsze byłyby fragmenty często powtarzanych dłuższych sekwencji, np. Tylko do odczytu poparte SerializeFieldpolem.

  5. Visual Studio oferuje również bardzo potężne narzędzie do generowania kodu, szablony tekstowe T4 (EF używa T4), chociaż osobiście uważam, że praktyczne zastosowanie w projektach Unity jest wątpliwe - są przesadne, dość skomplikowane, a kompilacja projektu prawdopodobnie zależałaby od Visual Studio.

wondra
źródło
To działało jak urok! Dodałem odpowiednie przestrzenie nazw dla przyszłych użytkowników. Miałem też jeszcze jeden problem, choć myślę, że może być dla mnie wyjątkowy; Nie mogę użyć Path.GetFileWithoutExtension. Mówi mi, że próbuje uzyskać dostęp do MonoBehaviour, co wydaje się dziwne. Dołączam przestrzeń nazw using Path = System.IO.Path.GetFileWithoutExtensioni tracę Pathwszystko razem. W końcu musiałem w pełni rozwinąć linię, samą ( .Contains("class " + System.IO.Path.GetFileNameWithoutExtension(assetPath)));).
Gnemlock,
Jaki jest najprostszy sposób, aby zapewnić tworzenie plików za pomocą LF i UTF-8 zamiast CRLF i UTF-8 z BOM?
Aaron Franke
@AaronFranke dobrze ... to raczej specyficzna prośba. Spróbowałbym zapytać na stackoverflow.com, jak zrobić string/ File.Writewyprowadzić tylko LF z BOM. O ile wiem „\ n” powinno być tylko LF, możesz też spróbować Environment.Newlinezamiast tego, ale powinien to być CRLF. Może również istnieć opcja użycia haków git, jeśli wszystko inne zawiedzie. BOM powinno być łatwe dzięki temu pytaniu o przepełnienie stosu .
wondra
15

Możesz znaleźć szablony skryptów do automatycznego generowania kodu w folderze instalacyjnym Unity. Znajduję szablony w „Unity / Editor / Data / Resources / ScriptTemplates” , podczas gdy inne źródła znalazły go w „Unity / Editor / Data / Resources” .

Ogólne szablony UnityScript i C # są identyfikowane odpowiednio jako pliki „82-JavaScript-NewBehaviourScript.js.txt” i „81-C # Script-NewBehaviourScript.cs.txt” . Możesz bezpośrednio edytować te pliki, aby zmienić sposób, w jaki Unity automatycznie generuje skrypt.

Możesz także dołączyć dodatkowe szablony, które pojawią się po wybraniu „Utwórz” w oknie „Projekt” . Wygląda na to, że szablony nie wymagają unikalnej numeracji i używają początkowego ciągu, aby określić hierarchię menu, gdzie „__” oznacza podmenu. Na przykład posiadanie pliku o nazwie „81-C # Script__Editor Script-NewBehaviourScript.cs.txt” zapewni dodatkowe menu „ C # Script” z opcją podrzędną umożliwiającą utworzenie „Script Editor” przy użyciu tego szablonu.

Czy nie zmieniać nazwy oryginalne szablony; są one wykorzystywane bardziej bezpośrednio przez silnik. Na przykład zmiana nazwy „81-C # Script-NewBehaviourScript.cs.txt” uniemożliwi dodawanie nowych skryptów C # jako składników bezpośrednio przez inspektora.


Poniżej znajduje się mój przykład, chociaż pokazuje on szczególne praktyki, do których jestem najbardziej przyzwyczajony. Na przykład wolę mieć niestandardowy skrypt edytora w tym samym pliku, co klasa docelowa, więc go kapsułkuję#if UNITY_EDITOR .. #endif , zamiast umieszczać w ogólnym folderze edytora „nie kompiluj w kompilacji”.

Nie jestem pewien, czy możliwe jest podanie kontekstu niestandardowej przestrzeni nazw; Po prostu używam „NAMESPACE”, ponieważ pozwala mi to zapewnić poprawną przestrzeń nazw po utworzeniu, używając powszechnie wbudowanej funkcji „find..replace all”.


Szablon:

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

Wyjście:

/* 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
źródło