ฉันจะกำหนดสคริปต์ที่สร้างขึ้นเองโดยอัตโนมัติได้อย่างไร


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
ฉันไม่เคยคิดที่จะทำสิ่งนี้ ขอบคุณที่ถาม! ตอนนี้ที่จะรวมสองคำตอบที่จะมีแม่แบบและแล้วแยกมันใส่ข้อมูลเพิ่มเติมเช่น namespace ...
Draco18s ไว้ใจไม่ SE

คำตอบ:


4

นอกจากนี้คุณยังสามารถ

  1. เพิ่มสคริปต์แก้ไขในโฟลเดอร์ทรัพย์สิน / บรรณาธิการที่สมัครสมาชิก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 Text Templates (EF ใช้ T4) แม้ว่าฉันจะพบว่าการใช้งานจริงสำหรับโครงการ Unity นั้นเป็นเรื่องที่ค่อนข้างซับซ้อนและการรวบรวมโครงการน่าจะขึ้นอยู่กับ Visual สตูดิโอ


สิ่งนี้ได้ผลเหมือนมีเสน่ห์! ฉันได้เพิ่มเนมสเปซที่เกี่ยวข้องสำหรับผู้ใช้ในอนาคต ฉันยังมีปัญหาอีกหนึ่งแม้ว่าฉันคิดว่ามันอาจจะเป็นหนึ่งที่ไม่ซ้ำกันสำหรับฉัน Path.GetFileWithoutExtensionฉันไม่สามารถใช้ มันบอกฉันว่ากำลังพยายามเข้าถึง a MonoBehaviourซึ่งดูเหมือนแปลก ฉันรวมเนมสเปซusing Path = System.IO.Path.GetFileWithoutExtensionและฉันเสียPathทั้งหมดไปด้วยกัน ในท้ายที่สุดฉันก็ต้องขนลุกบรรทัดทั้งหมดเอง ( .Contains("class " + System.IO.Path.GetFileNameWithoutExtension(assetPath)));)
Gnemlock

วิธีที่ง่ายที่สุดในการตรวจสอบให้แน่ใจว่าไฟล์ถูกสร้างด้วย LF และ UTF-8 แทนที่จะเป็น CRLF และ UTF-8 พร้อม BOM คืออะไร
Aaron Franke

@AaronFranke ดี ... นั่นเป็นคำขอที่ค่อนข้างเฉพาะ ฉันจะลองถาม stackoverflow.com วิธีสร้างstring/ File.Writeส่งออก LF-only กับ BOM เท่านั้น เท่าที่ฉันรู้ว่า '\ n' ควรเป็นแค่ LF คุณสามารถลองEnvironment.Newlineแทน แต่ควรเป็น CRLF นอกจากนี้ยังอาจมีตัวเลือกในการใช้ hooks git หากทุกอย่างอื่นล้มเหลว BOM ควรเป็นเรื่องง่ายด้วยคำถาม stackoverflowนี้
wondra

15

คุณสามารถค้นหาเทมเพลตสคริปต์สำหรับสร้างรหัสอัตโนมัติในโฟลเดอร์การติดตั้ง Unity ของคุณ ฉันพบแม่แบบภายใต้"ความสามัคคี / บรรณาธิการ / ข้อมูล / ทรัพยากรธรรมชาติ / ScriptTemplates"ขณะที่แหล่งอื่น ๆได้พบว่าภายใต้"ความสามัคคี / บรรณาธิการ / ข้อมูล / ทรัพยากร"

แม่แบบ 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แทนที่จะวางไว้ในโฟลเดอร์เอดิเตอร์ "ห้ามคอมไพล์ใน build" ทั่วไป

ฉันไม่แน่ใจว่าเป็นไปได้หรือไม่ที่จะกำหนดบริบทของเนมสเปซที่กำหนดเอง ฉันใช้ "NAMESPACE" เพียงอย่างเดียวเพราะมันช่วยให้ฉันสามารถสร้างเนมสเปซที่ถูกต้องได้โดยใช้ฟังก์ชั่น "find..replace all" ทั่วไปที่ inbuilt


แม่แบบ:

/* 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
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.