Examples
Buat transisi di jendela editor kustom

Buat jendela editor kustom

Jendela Editor kustom memungkinkan Anda untuk memperluas Unity dengan menerapkan editor dan alur kerja Anda sendiri. Panduan ini mencakup membuat jendela Editor melalui kode, bereaksi terhadap input pengguna, membuat UI(User Interface) Memungkinkan pengguna untuk berinteraksi dengan aplikasi Anda. Unity saat ini mendukung tiga sistem UI. More info
Lihat di Glossary
dapat diubah dan menangani pemuatan panas.

Dalam tutorial ini, Anda akan membuat browser spriteObjek grafis 2D. Jika Anda digunakan untuk bekerja di 3D, Sprites pada dasarnya hanya tekstur standar tetapi ada teknik khusus untuk menggabungkan dan mengelola tekstur sprite untuk efisiensi dan kenyamanan selama perkembangan. More info
Lihat di Glossary
, yang menemukan dan menampilkan semua kecambah dalam proyek, dan menunjukkan mereka sebagai daftar. Memilih sprite dalam daftar akan menampilkan gambar di sisi kanan jendela.

Anda dapat menemukan contoh lengkap di bagian skrip jendela editor.

Custom sprite browser
Browser sprite

Prerequisites

Panduan ini adalah untuk pengembang yang akrab dengan Unity, tetapi baru ke UI Toolkit. Disarankan untuk memiliki pemahaman dasar dari Unity dan C# scripting.

Panduan ini juga merujuk pada konsep berikut:

Content

Controls used in this guide:

Dalam panduan ini, Anda akan melakukan hal berikut:

  • Buat skrip jendela Editor.
  • Buat entri menu untuk membuka jendela.
  • Tambahkan kontrol UI ke jendela.
  • Tulis kode untuk menanggapi pilihan pengguna.
  • Buat UI yang dapat disesuaikan.
  • Mendukung pemuatan panas di Editor.

Buat skrip jendela Editor

Tip
Anda dapat menghasilkan kode yang diperlukan untuk membuat skrip jendela Editor di Editor Unity. Dari jendela Proyek, klik kanan dan pilih Create > UI Toolkit > Editor Window. Untuk panduan ini silakan menonaktifkan kotak centang UXML dan USS. Anda mungkin juga harus menambahkan petunjuk using tambahan di bagian atas file, seperti yang ditunjukkan di bawah ini.

Anda dapat membuat jendela Editor melalui C# scriptsSepotong kode yang memungkinkan Anda untuk membuat Komponen Anda sendiri, memicu peristiwa permainan, memodifikasi sifat komponen dari waktu ke waktu dan menanggapi input pengguna dengan cara apa pun yang Anda sukai. More info
Lihat di Glossary
dalam proyek Anda. Jendela editor kustom adalah kelas yang berasal dari kelas EditorWindow.

Buat file skrip baru MyCustomEditor.cs di bawah folder Assets/Editor. Tempel kode berikut ke script:

using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class MyCustomEditor : EditorWindow
{
}
Note
Ini adalah jendela Editor-only yang mencakup ruang nama UnityEditor, sehingga file harus ditempatkan di bawah Editor, atau di dalam Definisi Perakitan Editor-only.

Buat entri menu untuk membuka jendela

Untuk membuka jendela Editor baru, Anda harus membuat entri di menu Editor.

Tambahkan atribut MenuItem ke metode statis. Dalam contoh ini, nama metode statis adalah ShowMyEditor().

Di dalam ShowMyEditor(), sebut metode EditorWindow.GetWindow() untuk membuat dan menampilkan jendela. Ini mengembalikan objek EditorWindow. Untuk mengatur judul jendela, mengubah properti WordPress.org.

Tambahkan fungsi berikut di dalam kelas MyCustomEditor yang dibuat pada langkah sebelumnya.

[MenuItem("Tools/My Custom Editor")]
public static void ShowMyEditor()
{
  // This method is called when the user selects the menu item in the Editor
  EditorWindow wnd = GetWindow<MyCustomEditor>();
  wnd.titleContent = new GUIContent("My Custom Editor");
}

Uji jendela baru Anda dengan membukanya melalui menu Unity Editor Tools > My Custom Editor.

Editor window with custom title
Jendela editor dengan judul kustom

Tambahkan kontrol UI ke jendela

UI Toolkit menggunakan metode CreateGUI untuk menambahkan kontrol ke Editor UI, dan Unity memanggil metode CreateGUI secara otomatis ketika jendela perlu ditampilkan. Metode ini bekerja sama seperti metode seperti Awake atau Update.

Anda dapat menambahkan kontrol UI ke UI dengan menambahkan elemen visual ke pohon visual. Metode Login Login digunakan untuk menambahkan anak ke elemen visual yang ada. pohon visual dari jendela Editor diakses melalui properti rootvisualElement.

Untuk memulai, tambahkan fungsi CreateGUI() ke kelas editor kustom Anda dan tambahkan label 'Hello':

public void CreateGUI()
{
  rootVisualElement.Add(new Label("Hello"));
}
Window with Hello label
Jendela dengan label 'Hello'
Note
Untuk menyajikan daftar kecambah, gunakan fungsi AssetDatabase untuk menemukan semua kecambah dalam proyek.

Ganti kode di dalam CreateGUI() dengan kode di bawah untuk menghitung semua kecambah dalam proyek.

public void CreateGUI()
{
  // Get a list of all sprites in the project
  var allObjectGuids = AssetDatabase.FindAssets("t:Sprite");
  var allObjects = new List<Sprite>();
  foreach (var guid in allObjectGuids)
  {
    allObjects.Add(AssetDatabase.LoadAssetAtPath<Sprite>(AssetDatabase.GUIDToAssetPath(guid)));
  }
}

Untuk browser sprite, elemen visual tingkat atas akan menjadi TwoPaneSplitView. Kontrol ini membagi ruang jendela yang tersedia menjadi dua panci: satu ukuran tetap dan satu ukuran fleksibel. Ketika Anda mengubah ukuran jendela, hanya pane fleksibel resizes, sementara pane ukuran tetap tetap tetap ukuran yang sama.

Untuk kontrol TwoPaneSplitView untuk bekerja, perlu memiliki dua anak. Tambahkan kode di dalam CreateGUI() untuk membuat TwoPaneSplitview, kemudian tambahkan dua elemen anak sebagai placeholder untuk kontrol yang berbeda.

// Create a two-pane view with the left pane being fixed with
var splitView = new TwoPaneSplitView(0, 250, TwoPaneSplitViewOrientation.Horizontal);

// Add the view to the visual tree by adding it as a child to the root element
rootVisualElement.Add(splitView);

// A TwoPaneSplitView always needs exactly two child elements
var leftPane = new VisualElement();
splitView.Add(leftPane);
var rightPane = new VisualElement();
splitView.Add(rightPane);

Gambar di bawah ini menunjukkan jendela kustom dengan dua panel kosong. Bar divider dapat dipindahkan.

Window with two split panes
Jendela dengan dua panci split

Untuk peramban sprite, pane kiri akan menjadi daftar yang berisi nama semua kecambah yang ditemukan di proyek. Skema kontrol ListView dari VisualElement, sehingga mudah untuk memodifikasi kode untuk menggunakan ListView bukan VisualElement kosong.

Modifikasi kode di dalam fungsi CreateGUI() untuk membuat kontrol ListView untuk pane kiri bukan VisualElement.

public void CreateGUI()
{
  ...
  var leftPane = new ListView();
  splitView.Add(leftPane);
  ...
}

Kontrol ListView menampilkan daftar item yang dapat dipilih. Dioptimalkan untuk membuat elemen yang cukup untuk menutupi area yang terlihat, dan kolam renang dan mendaur ulang elemen visual saat Anda menggulir daftar. Ini mengoptimalkan kinerja dan mengurangi jejak memori, bahkan dalam daftar yang memiliki banyak item.

Untuk mengambil keuntungan dari ini, ListView harus benar diinisialisasikan dengan berikut:

  • Berbagai item data.
  • Fungsi callback untuk membuat entri daftar visual individu dalam daftar.
  • Fungsi mengikat yang menginisialisasi entri daftar visual dengan item dari array data.

Anda dapat membuat struktur UI yang kompleks untuk setiap elemen dalam daftar, tetapi contoh ini menggunakan label teks sederhana untuk menampilkan nama sprite.

Tambahkan kode ke fungsi bawah CreateGUI() yang menginisialisasikan ListView.

public void CreateGUI()
{
  ...
  // Initialize the list view with all sprites' names
  leftPane.makeItem = () => new Label();
  leftPane.bindItem = (item, index) => { (item as Label).text = allObjects[index].name; };
  leftPane.itemsSource = allObjects;
}

Gambar di bawah ini menunjukkan jendela Editor dengan tampilan daftar yang dapat digulir dan item yang dapat dipilih.

ListView with sprite names
DaftarView dengan nama sprite

Untuk referensi, di bawah ini adalah kode saat ini untuk fungsi CreateGUI() dalam keseluruhannya:

public void CreateGUI()
{
  // Get a list of all sprites in the project
  var allObjectGuids = AssetDatabase.FindAssets("t:Sprite");
  var allObjects = new List<Sprite>();
  foreach (var guid in allObjectGuids)
  {
    allObjects.Add(AssetDatabase.LoadAssetAtPath<Sprite>(AssetDatabase.GUIDToAssetPath(guid)));
  }

  // Create a two-pane view with the left pane being fixed with
  var splitView = new TwoPaneSplitView(0, 250, TwoPaneSplitViewOrientation.Horizontal);

  // Add the panel to the visual tree by adding it as a child to the root element
  rootVisualElement.Add(splitView);

  // A TwoPaneSplitView always needs exactly two child elements
  var leftPane = new ListView();
  splitView.Add(leftPane);
  var rightPane = new VisualElement();
  splitView.Add(rightPane);

  // Initialize the list view with all sprites' names
  leftPane.makeItem = () => new Label();
  leftPane.bindItem = (item, index) => { (item as Label).text = allObjects[index].name; };
  leftPane.itemsSource = allObjects;
}

Tambahkan callback

Ketika Anda memilih sprite dari daftar di pane kiri, gambarnya harus ditampilkan pada pane yang tepat. Untuk melakukan ini Anda perlu memberikan fungsi callback yang dapat dihubungi ListView ketika pengguna membuat pilihan. Kontrol ListView memiliki properti onSelectionChange untuk tujuan ini.

Fungsi callback menerima daftar yang berisi item atau item yang dipilih oleh pengguna. Mungkin untuk mengkonfigurasi ListView untuk memungkinkan multi-selection, tetapi secara default mode pemilihan terbatas pada satu item.

Tambahkan fungsi callback ketika pengguna mengubah pilihan dari daftar di pane kiri.

public void CreateGUI()
{
  ...

  // React to the user's selection
  leftPane.onSelectionChange += OnSpriteSelectionChange;
}

private void OnSpriteSelectionChange(IEnumerable<object> selectedItems)
{
}
Note
Jika Anda kehilangan jendela Anda dan menu tidak membuka kembali, tutup semua panel mengambang melalui menu di bawah Window > Panels, atau mengatur ulang tata letak jendela Anda.Close all floating panels, or reset your window layout.

Untuk menampilkan gambar sprite yang dipilih di sisi kanan jendela, fungsi harus dapat mengakses pane tangan kanan dari TwoPaneSplitView. Anda dapat membuat kontrol ini variabel anggota kelas untuk dapat mengaksesnya di dalam fungsi callback.

Mengubah rightPane dibuat dalam CreateGUI() menjadi variabel anggota.

private VisualElement m_RightPane;

public void CreateGUI()
{
  ...

  m_RightPane = new VisualElement();
  splitView.Add(m_RightPane);

  ...
}

Dengan referensi ke TwoPaneSplitView, Anda dapat mengakses pane yang tepat melalui properti flexedPane. Sebelum membuat kontrol Image baru pada pane yang tepat, gunakan VisualElement.Clear() untuk menghapus gambar sebelumnya. Metode ini menghilangkan semua anak-anak dari elemen visual yang ada.

Jelaskan pane yang tepat dari semua konten sebelumnya dan buat kontrol Gambar baru untuk sprite yang dipilih.

private void OnSpriteSelectionChange(IEnumerable<object> selectedItems)
{
  // Clear all previous content from the pane
  m_RightPane.Clear();

  // Get the selected sprite
  var selectedSprite = selectedItems.First() as Sprite;
  if (selectedSprite == null)
    return;

  // Add a new Image control and display the sprite
  var spriteImage = new Image();
  spriteImage.scaleMode = ScaleMode.ScaleToFit;
  spriteImage.sprite = selectedSprite;

  // Add the Image control to the right-hand pane
  m_RightPane.Add(spriteImage);
}
Note
Pastikan untuk menyertakan using System.Linq; di bagian atas file Anda untuk menggunakan metode First() pada parameter selectedItems.

Uji browser sprite Anda di Editor. Gambar di bawah ini menunjukkan jendela editor kustom dalam tindakan.

Sprite browser in action
Peramban Sprite dalam aksi

Membuat UI dapat disesuaikan

Windows editor dapat diakses dalam dimensi minimum dan maksimum yang diperbolehkan. Anda dapat mengatur dimensi ini di C# ketika membuat jendela dengan menulis ke properti WordPress.org dan WordPress.org. Untuk mencegah jendela dari resizing, menetapkan dimensi yang sama untuk kedua properti.

Batasi ukuran jendela editor kustom Anda dengan menambahkan garis-garis berikut ke bagian bawah fungsi ShowMyEditor():

[MenuItem("Tools/My Custom Editor")]
public static void ShowMyEditor()
{
  // This method is called when the user selects the menu item in the Editor
  EditorWindow wnd = GetWindow<MyCustomEditor>();
  wnd.titleContent = new GUIContent("My Custom Editor");

  // Limit size of the window
  wnd.minSize = new Vector2(450, 200);
  wnd.maxSize = new Vector2(1920, 720);
}

Untuk situasi di mana dimensi jendela terlalu kecil untuk menampilkan seluruh UI, Anda harus menggunakan elemen ScrollView untuk menyediakan gulir untuk jendela, atau konten mungkin menjadi tidak dapat diakses.

ListView pada pane kiri menggunakan ScrollView internal, tetapi pane yang tepat adalah VisualElement biasa. Mengubah ini ke kontrol ScrollView secara otomatis menampilkan scrollbars ketika jendela terlalu kecil untuk menyesuaikan seluruh gambar dalam ukuran aslinya.

Tukar pane yang tepat VisualElement untuk gulir dua arah.ScrollView with bidirectional scrolling.

public void CreateGUI()
{
  ...

  m_RightPane = new ScrollView(ScrollViewMode.VerticalAndHorizontal);
  splitView.Add(m_RightPane);

  ...
}

Gambar di bawah ini menunjukkan jendela browser sprite dengan scrollbars.

Editor window with scrollbars
Jendela editor dengan scrollbars

Tutup dan buka kembali jendela editor kustom Anda untuk menguji batas ukuran baru.

Note
Pada Unity 2021.2 dan atas, Unity tidak menghormati sifat minSize dan maxSize ketika jendela didermaga. Ini memungkinkan pengguna untuk mengubah ukuran area dock tanpa batasan. Pertimbangkan membuat ScrollView sebagai salah satu elemen tingkat atas Anda dan letakkan semua UI di dalamnya untuk membuat UI Anda responsif mungkin.

Mendukung pemuatan panas di Editor

Jendela Editor yang tepat harus bekerja dengan alur kerja yang memuat panas yang terjadi di Editor Unity. Reload domain C# terjadi ketika skrip recompile atau ketika editor memasuki mode Play. Anda dapat mempelajari lebih lanjut tentang topik ini di halaman Serialisasi Script.

Untuk melihat ini dalam aksi di jendela Editor Anda hanya diciptakan, buka browser sprite, pilih sprite, dan kemudian masukkan mode Play. Reset jendela, dan pilihan hilang.

Karena objek VisualElement tidak serializable, UI harus dibuat kembali setiap kali reload terjadi pada Unity. Ini berarti bahwa metode CreateGUI() divoked setelah reload selesai. Ini memungkinkan Anda mengembalikan state UI sebelum reload dengan menyimpan data yang diperlukan dalam kelas EditorWindow Anda.

Tambahkan variabel anggota untuk menyimpan indeks yang dipilih dalam daftar sprite.

public class MyCustomEditor : EditorWindow
{
    [SerializeField] private int m_SelectedIndex = -1;

    ....
}

Ketika Anda membuat pilihan, indeks seleksi baru dari tampilan daftar dapat disimpan di dalam variabel anggota ini. Anda dapat mengembalikan indeks seleksi selama penciptaan UI di dalam fungsi CreateGUI().

Tambahkan kode ke akhir fungsi CreateGUI() untuk menyimpan dan mengembalikan indeks daftar yang dipilih.

public void CreateGUI()
{
  ...

  // Restore the selection index from before the hot reload
  leftPane.selectedIndex = m_SelectedIndex;

  // Store the selection index when the selection changes
  leftPane.onSelectionChange += (items) => { m_SelectedIndex = leftPane.selectedIndex; };
}

Pilih sprite dari daftar dan masukkan mode Play untuk menguji beban panas.

skrip jendela editor

Kode di bawah ini adalah skrip terakhir dari jendela Editor yang dibuat selama panduan ini. Anda dapat menempelkan kode langsung ke file yang disebut MyCustomEdtior.cs di dalam folder Assets/Editor untuk melihatnya di Editor Unity.

using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class MyCustomEditor : EditorWindow
{
  [SerializeField] private int m_SelectedIndex = -1;
  private VisualElement m_RightPane;

  [MenuItem("Tools/My Custom Editor")]
  public static void ShowMyEditor()
  {
    // This method is called when the user selects the menu item in the Editor
    EditorWindow wnd = GetWindow<MyCustomEditor>();
    wnd.titleContent = new GUIContent("My Custom Editor");

    // Limit size of the window
    wnd.minSize = new Vector2(450, 200);
    wnd.maxSize = new Vector2(1920, 720);
  }

  public void CreateGUI()
  {
    // Get a list of all sprites in the project
    var allObjectGuids = AssetDatabase.FindAssets("t:Sprite");
    var allObjects = new List<Sprite>();
    foreach (var guid in allObjectGuids)
    {
      allObjects.Add(AssetDatabase.LoadAssetAtPath<Sprite>(AssetDatabase.GUIDToAssetPath(guid)));
    }

    // Create a two-pane view with the left pane being fixed with
    var splitView = new TwoPaneSplitView(0, 250, TwoPaneSplitViewOrientation.Horizontal);

    // Add the panel to the visual tree by adding it as a child to the root element
    rootVisualElement.Add(splitView);

    // A TwoPaneSplitView always needs exactly two child elements
    var leftPane = new ListView();
    splitView.Add(leftPane);
    m_RightPane = new ScrollView(ScrollViewMode.VerticalAndHorizontal);
    splitView.Add(m_RightPane);

    // Initialize the list view with all sprites' names
    leftPane.makeItem = () => new Label();
    leftPane.bindItem = (item, index) => { (item as Label).text = allObjects[index].name; };
    leftPane.itemsSource = allObjects;

    // React to the user's selection
    leftPane.onSelectionChange += OnSpriteSelectionChange;

    // Restore the selection index from before the hot reload
    leftPane.selectedIndex = m_SelectedIndex;

    // Store the selection index when the selection changes
    leftPane.onSelectionChange += (items) => { m_SelectedIndex = leftPane.selectedIndex; };
  }

  private void OnSpriteSelectionChange(IEnumerable<object> selectedItems)
  {
    // Clear all previous content from the pane
    m_RightPane.Clear();

    // Get the selected sprite
    var selectedSprite = selectedItems.First() as Sprite;
    if (selectedSprite == null)
      return;

    // Add a new Image control and display the sprite
    var spriteImage = new Image();
    spriteImage.scaleMode = ScaleMode.ScaleToFit;
    spriteImage.sprite = selectedSprite;

    // Add the Image control to the right-hand pane
    m_RightPane.Add(spriteImage);
  }
}

Examples
Buat transisi di jendela editor kustom