UnityのUI Toolkitでバインドしたプロパティの変更をトラッキングする方法についてまとめました。
Unity 2022.2.19
UI Toolkitにおけるバインド
UI Toolkitでは、以下の記事のようにしてシリアライズされた値とUI要素をバインドすることができます。
いま、バインドした要素が変更された時に何かしらの処理をしたたいケースを考えます。
SerializedPropertyの変更をトラッキングする
値の変更をトラッキングするには、以下のようにVisualElement.TrackPropertyValue
を使います。
using UnityEditor; using UnityEditor.UIElements; using UnityEngine; using UnityEngine.UIElements; public sealed class Example : EditorWindow { private TextField _textField; public void CreateGUI() { _textField = new TextField("Object Name"); rootVisualElement.Add(_textField); Bind(Selection.activeObject); } private void OnSelectionChange() { Bind(Selection.activeObject); } [MenuItem("Window/Example")] public static void ShowWindow() { GetWindow<Example>(); } private void Bind(Object obj) { if (obj != null) { var so = new SerializedObject(obj); var property = so.FindProperty("m_Name"); _textField.Unbind(); // トラッキングする前にUnbindしておく _textField.BindProperty(property); _textField.TrackPropertyValue(property, OnNameChanged); // トラッキング OnNameChanged(property); } else { _textField.Unbind(); _textField.value = ""; } } private void OnNameChanged(SerializedProperty property) { Debug.Log("Name Changed : " + property.stringValue); if (property.stringValue.Contains(" ")) _textField.style.backgroundColor = Color.red; else _textField.style.backgroundColor = StyleKeyword.Null; } }
今回は前節で紹介した記事のEditorWindow
に、名前のチェック処理を加えました。
名前に半角スペースが入っていたらテキストフィールドを赤くしています。
SerializedObjectの変更をトラッキングする
SerializedObject
とバインディングしている場合には、同じように、TrackSerializedObjectValue
を使うことで値の変更をトラッキングできます。
using UnityEditor; using UnityEditor.UIElements; using UnityEngine; using UnityEngine.UIElements; public sealed class Example : EditorWindow { private TextField _textField; public void CreateGUI() { _textField = new TextField("Object Name") { bindingPath = "m_Name" // SerializedObjectとバインドするためここでパスを入力しておく }; rootVisualElement.Add(_textField); Bind(Selection.activeObject); } private void OnSelectionChange() { Bind(Selection.activeObject); } [MenuItem("Window/Example")] public static void ShowWindow() { GetWindow<Example>(); } private void Bind(Object obj) { if (obj != null) { var so = new SerializedObject(obj); rootVisualElement.Unbind(); // トラッキングする前にUnbindしておく rootVisualElement.Bind(so); rootVisualElement.TrackSerializedObjectValue(so, OnValueChanged); // トラッキング OnValueChanged(so); } else { rootVisualElement.Unbind(); _textField.value = ""; } } private void OnValueChanged(SerializedObject so) { Debug.Log("Name changed: " + so.targetObject.name); var nameProperty = so.FindProperty("m_Name"); if (nameProperty.stringValue.Contains(" ")) _textField.style.backgroundColor = Color.red; else _textField.style.backgroundColor = StyleKeyword.Null; } }