なつねこメモ

主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ

書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。

2022/02/16

Unity の UXML で Binding したフィールドの変更を受け取りたい

カテゴリー:C#Unity

C# + UXML でエディター拡張を書いている際、  Binding 中の変数に対して、値が代入されるタイミングである処理を呼びたい、みたいなことはあると思うんですが、その方法の紹介です。
といっても Unity 2019 と 2020 では微妙にやり方が変わっているので、今回は Unity 2019 版でのお話。

まず、以下のような UXML があるとします。

<?xml version="1.0" encoding="utf-8" ?>
<engine:UXML
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:engine="UnityEngine.UIElements"
  xmlns:editor="UnityEditor.UIElements"
  xsi:noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd"
>
  <engine:ScrollView class="min-h-full">
    <engine:VisualElement class="container mx-auto my-4">
      <engine:VisualElement class="my-2">
        <engine:TextElement
          text="アバター着せ替えエディター"
          class="text-2xl mb-2"
        />

        <engine:TextElement
          text="衣装を着せたいアバターと対応している衣装、アクセサリーなどを簡単に着せ替え、調節することが出来ます。"
          class="text-lg"
        />
      </engine:VisualElement>
      <engine:VisualElement class="my-2">
        <editor:PropertyField name="_avatar" label="アバター" />
      </engine:VisualElement>
    </engine:VisualElement>
  </engine:ScrollView>
</engine:UXML>

この場合、 _avatar に値が Binding されると考えて、この値が変わったタイミングで、何らかのバリデーションをしたいとします。
その場合は、このように書くことで出来ます。

private SerializedObject _so;

private void CreateGUI()
{
    // 省略
    var element = rootVisualElement.Q<PropertyField>("_avatar");
    element.BindProperty(_so.FindProperty("_avatar"));
    element.RegisterCallback<ChangeEvent<Object>>(w => { /* ここに処理を入れる */});
}

このとき、 ChangeEvent の Generics に渡す型パラメータは UnityEngine.Object である必要があります。
他の型を指定するとコールバックは呼ばれることはありませんでした。

ちなみに、 IntField とかの場合は、 RegisterValueChangedCallback を使うことで、同様のことが出来ます。
ということで、今日のメモでした。