前回はコールバックを作成しましたが、今回は独自のコントロールを作ってみましょう!
ということで、早速 UXML と C# スクリプトを書きます。
たとえば、こんな感じのメッセージボックスを作りたい場合は、

以下のような 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:VisualElement class="flex flex-row border-2 border-slate-400 rounded-md p-2 my-2 items-center"> <engine:VisualElement class="flex justify-center items-center"> <engine:Image name="icon" class="w-10 h-10 min-h-full" /> </engine:VisualElement> <engine:VisualElement class="flex-grow ml-2"> <engine:TextElement name="text" class="text-lg" /> </engine:VisualElement> </engine:VisualElement> </engine:UXML>
そして、これの icon と text 部分を、親コンポーネントから受け取る値だったとします。
その場合、次のような C# スクリプトを記述します。
// ------------------------------------------------------------------------------------------
// Copyright (c) Natsuneko. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
// ------------------------------------------------------------------------------------------
using System.Collections.Generic;
using NatsunekoLaboratory.VRAvatarToolkit.Enums;
using NatsunekoLaboratory.VRAvatarToolkit.Extensions;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace NatsunekoLaboratory.VRAvatarToolkit.Controls
{
public class MessageBox : VisualElement
{
private readonly Image _icon;
private readonly TextElement _text;
public MessageBoxIcon Icon
{
set => _icon.style.backgroundImage = new StyleBackground(Background.FromTexture2D(EditorGUIUtility.Load(value.ToResourceString()) as Texture2D));
}
public string Text
{
get => _text.text;
set => _text.text = value;
}
public MessageBox()
{
// UXML / USS 読み込み部分は省略
_icon = this.Q<Image>("icon");
_text = this.Q<TextElement>("text");
}
public new class UxmlFactory : UxmlFactory<MessageBox, UxmlTraits> { }
public new class UxmlTraits : VisualElement.UxmlTraits
{
private readonly UxmlEnumAttributeDescription<MessageBoxIcon> _icon = new UxmlEnumAttributeDescription<MessageBoxIcon> { name = "icon", defaultValue = MessageBoxIcon.Info };
private readonly UxmlStringAttributeDescription _text = new UxmlStringAttributeDescription { name = "text", defaultValue = "" };
public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
{
get { yield break; }
}
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
{
base.Init(ve, bag, cc);
((MessageBox)ve).Text = _text.GetValueFromBag(bag, cc);
((MessageBox)ve).Icon = _icon.GetValueFromBag(bag, cc);
}
}
}
}
該当コントロールのクラス実装のインナークラスとして、 UxmlTraits みたいな感じで作ってあげると、バインディングされた値を受け取ることが出来ます。
最後に、 Init メソッド経由で受け取れば、初期値がバインドされます。
2回目以降は普通に C# スクリプトからプロパティ経由でアクセス可能なので、特に実装は必要ありません。
ということで、今日のメモでした!