Unity:UI Elements で共通コントロールを作成する

最終更新日

はじめに

たっつー(管理人)
たっつー(管理人)

こんにちは、のんびりエンジニアのたっつーです。

今回は「いくつかサンプル書いたよ」の記事の1つの共通コントロールの作成方法と使い方を解説したいと思います。
ぜひ、お付き合いいただければと思います(#^^#)

UI Elementsとは?

こちらの記事をご参照いただければと思います。

共通コントロールの実装

さっそくですが、共通コントロールの実装をしてみたいと思います。

共通コントロール

Editor フォルダを作成し、右クリックのメニューから「UIElements Editor Window」を選択してください。

「RedButton」を入力してください。
 ※つけたいコントロールの名前に変更してしまって、OKです。

以下の3ファイルが生成されました、次にこの3ファイルを編集したいとおもいます。

まずは、RedButton.uxml は使わないので削除してください!
※使っても実装できますが今回はスクリプトですべて生成していきます。



次に、RedButton.uss を以下のように変更してください。

Button {
    font-size: 15px;
    -unity-font-style: bold;
    color: rgb(255, 0, 0);
}

次に、RedButton.cs を以下のように変更してください。

また、独自イベントとして clicked を定義しており、ボタンを押下イベントに合わせて clicked が呼ばれるようにしております。
また、MyControls のネームスペースに変更するのをお忘れずに!

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


namespace MyControls
{
    internal class RedButton : VisualElement
    {
        public new class UxmlFactory : UxmlFactory<RedButton, UxmlTraits> { }

        public new class UxmlTraits : VisualElement.UxmlTraits
        {
            UxmlStringAttributeDescription m_Text =
                new UxmlStringAttributeDescription { name = "text", defaultValue = "none label" };

            public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
            {
                get { yield break; }
            }

            public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
            {
                base.Init(ve, bag, cc);
                var text = m_Text.GetValueFromBag(bag, cc);
                ((RedButton)ve).Init(text);
            }
        }

        private Button m_button;

        public string text
        {
            get { return m_button.text; }
            set { m_button.text = value; }
        }

        public event Action<EventBase> clicked;

        public RedButton()
        {
            var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Editor/RedButton.uss");
            styleSheets.Add(styleSheet);

            m_button = new Button();
            m_button.text = "noen label";
            m_button.clickable.clickedWithEventInfo += Button_Clicked;
            hierarchy.Add(m_button);
        }

        public RedButton(string text) : this()
        {
            Init(text);
        }

        public void Init(string text)
        {
            this.text = text;
        }

        private void Button_Clicked(EventBase eb)
        {
            eb.target = this;
            clicked?.Invoke(eb);
        }
    }
}

呼び出し側

次に呼び出し側の実装になります。
先ほどと同じよう入力ですが今回は「Sample1」で追加してください。

同じように3ファイルとも以下のように編集してください。

共通コントロールとして、以下の赤い文字のボタン(RedButton)を用意しました、これを使いまわせるパーツとして、ボタン1~3の計3つを作成しています。

ポイントとしては、「xmlns:my=”MyControls”」 で my:RedButton が使えるようになります。

<?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"
    xmlns:my="MyControls"
    xsi:noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd"
    xsi:schemaLocation="UnityEngine.UIElements ../../UIElementsSchema/UnityEngine.UIElements.xsd">

  <engine:Label text="Sample1 UXML" />

  <my:RedButton text="button1" name="btn1" />
  <my:RedButton text="button2" name="btn2" />
  <my:RedButton text="button3" name="btn3" />

  <engine:Label text="Sample1 UXML end" />
</engine:UXML>
Label {
    font-size: 20px;
    -unity-font-style: bold;
    color: rgb(68, 138, 255);
}

ポイントとしては、各ボタンイベント(Clicked)にイベントを紐づけるために「root.Q(“btn1”).clicked += ButtonClicked;」で実行しています。

using MyControls;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class Sample1 : EditorWindow
{
    [MenuItem("UIElementsSamples/Sample1")]
    public static void ShowExample()
    {
        Sample1 wnd = GetWindow<Sample1>();
        wnd.titleContent = new GUIContent("Sample1");
    }

    public void OnEnable()
    {
        VisualElement root = rootVisualElement;

        var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/Sample1.uxml");
        VisualElement labelFromUXML = visualTree.CloneTree();
        root.Add(labelFromUXML);

        root.Q<RedButton>("btn1").clicked += ButtonClicked;
        root.Q<RedButton>("btn2").clicked += ButtonClicked;
        root.Q<RedButton>("btn3").clicked += ButtonClicked;
    }

    void ButtonClicked(EventBase eventBase)
    {
        var redButton = (RedButton)eventBase.target;
        Debug.Log($"Clicked {redButton.text} RedButton!! ");
    }
}

動作結果

どうでしたか簡単に実装が行えたと思います。
今回は、RedButton.uxml は使わない実装でしたが使って実装する場合もそんなに難しくないと思いますのでぜひチャレンジしてみてください!

次に読んでほしい記事







よければ、SNSにシェアをお願いします!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

コメントする