バージョン: 2021.3 以降
この例では、カスタムコントロールをカスタムデータ型にバインドする方法を説明します。
この例では、3 つのビルトインコントロールに基づき、カスタムデータ型とカスタムコントロールを作成します。カスタムコントロールは、カスタムデータ型にバインドされます。ドロワーは、Celsius (摂氏) と Fahrenheit (華氏) の変換を行います。
この例で作成するすべてのファイルは、GitHub リポジトリ にあります。
This guide is for developers familiar with the Unity Editor, UI Toolkit, and C# scripting. You are recommended to have a basic understanding of the following:
カスタムデータ型 Temperature
を作成し、シリアル化されたプロパティとして使用します。
任意のテンプレートで Unity プロジェクトを作成します。
bind-custom-data-type
というフォルダーを作成し、すべてのファイルを保存します。
Temperature.cs
という名の C# スクリプトを作成し、そのコンテンツを以下に置き換えます。
using System;
namespace UIToolkitExamples
{
public enum TemperatureUnit
{
Celsius,
Farenheit
}
[Serializable]
public struct Temperature
{
public double value;
public TemperatureUnit unit;
}
}
PlanetScript.cs
という名の C# スクリプトを作成し、そのコンテンツを以下に置き換えます。
using UnityEngine;
namespace UIToolkitExamples
{
public class PlanetScript : MonoBehaviour
{
public Temperature coreTemperature;
}
}
Planet
のカスタムエディターと、 Temperature
のカスタムプロパティドロワーを作成します。
カスタムプロパティドロワーで、温度を華氏と摂氏間で変換するボタンを実装します。それを行うには、SerializedProperty
(doubleValue
と enumValueIndex
を使用) のプロパティに書き込み、それから、SerializedObject.ApplyModifiedProperties()
を呼び出します。
カスタムプロパティドロワーは、カスタムコントロールとして扱われます。これは、カスタムの方法で動作するビルトインのコントロールです。
Editor
という名前のフォルダーを作成します。
Editor フォルダーに、PlanetEditor.cs
という名の C# スクリプトを作成し、そのコンテンツを以下に置き換えます。
using UnityEditor;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
namespace UIToolkitExamples
{
[CustomEditor(typeof(PlanetScript))]
public class PlanetEditor : Editor
{
public override VisualElement CreateInspectorGUI()
{
return new PropertyField(serializedObject.FindProperty("coreTemperature"));
}
}
}
Editor フォルダーに TemperatureDrawer.cs
という名の C# スクリプトを作成し、そのコンテンツを以下に置き換えます。
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace UIToolkitExamples
{
[CustomPropertyDrawer(typeof(Temperature))]
public class TemperatureDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var asset = Resources.Load<VisualTreeAsset>("temperature_drawer");
var drawer = asset.Instantiate(property.propertyPath);
drawer.Q<Label>().text = property.displayName;
// Don't allow conversion when you've selected multiple objects in the Inspector
if (!property.serializedObject.isEditingMultipleObjects)
{
drawer.Q<Button>().RegisterCallback<ClickEvent, SerializedProperty>(Convert, property);
}
return drawer;
}
static void Convert(ClickEvent evt, SerializedProperty property)
{
var valueProperty = property.FindPropertyRelative("value");
var unitProperty = property.FindPropertyRelative("unit");
// F -> C
if (unitProperty.enumValueIndex == (int)TemperatureUnit.Farenheit)
{
valueProperty.doubleValue -= 32;
valueProperty.doubleValue *= 5.0d / 9.0d;
unitProperty.enumValueIndex = (int)TemperatureUnit.Celsius;
}
else // C -> F
{
valueProperty.doubleValue *= 9.0d / 5.0d;
valueProperty.doubleValue += 32;
unitProperty.enumValueIndex = (int)TemperatureUnit.Farenheit;
}
// Important: Because you are bypassing the binding system, you must save the modified SerializedObject
property.serializedObject.ApplyModifiedProperties();
}
}
}
以下を持つ UXML ファイルを作成します。
2 つのフィールドの binding-path
を Temperature
プロパティの value
と unit
に設定します。
Editor フォルダーに、Resources
という名前のフォルダーを作成します。
Resources フォルダーに、temperature_drawer.uxml
という名の UI ドキュメントを作成し、そのコンテンツを以下に置き換えます。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:VisualElement class="unity-base-field">
<ui:Label class="unity-base-field__label" />
<ui:VisualElement class="unity-base-field__input" style="flex-direction: row;">
<uie:DoubleField binding-path="value" />
<uie:EnumField binding-path="unit" />
<ui:Button text="Convert" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
Temperature
プロパティが変更されます。