Unity UI Toolkit カスタムコントロールサンプル

始めに

UI Toolkit でのカスタムコントロール その2 です。

主にデフォルト動作を変えるためのものです。

以前の記事

参考

【UI Toolkit】Unity6 で UiBuilder 上で Image タグを Library から使用できるように拡張する https://qiita.com/john95206/items/8e7498f1dfb894396383

サンプルコード

using UnityEngine;
using UnityEngine.UIElements;

namespace Assets.MyUI
{
    [UxmlElement]
    public partial class MyButton : Button
    {
        public MyButton()
        {
            selection.doubleClickSelectsWord = false;
            selection.tripleClickSelectsLine = false;
            enableRichText = false;
            displayTooltipWhenElided = false;

            blocker = new VisualElement();
            blocker.style.position = Position.Absolute;
            blocker.style.top = 0;
            blocker.style.left = 0;
            blocker.style.right = 0;
            blocker.style.bottom = 0;
            blocker.pickingMode = PickingMode.Position;

            Add(blocker);
        }

        VisualElement blocker;

        public void SetIconImage(Sprite sprite)
        {
            iconImage = Background.FromSprite(sprite);
        }

        public void SetEnabledAndClickable(bool enabled)
        {
            //SetEnabled(enabled);//子であるblokerも無効化される。自前で見た目とクリックの有効/無効を切り替える
            style.opacity = enabled ? 1f : 0.5f;
            blocker.style.display = enabled ? DisplayStyle.None : DisplayStyle.Flex;
        }
    }
}

SetEnabledをした時にクリックが背面に貫通してしまう対策をしています。

using Unity.Properties;
using UnityEngine;
using UnityEngine.UIElements;

namespace Assets.MyUI
{
    [UxmlElement]
    public partial class MyImage : VisualElement
    {
        [CreateProperty]
        [UxmlAttribute]
        public Sprite ImageSprite
        {
            get => _image.sprite;
            set
            {
                _image.sprite = value;
            }
        }

        private readonly Image _image;

        public MyImage()
        {
            _image = new Image();

            Add(_image);

            style.flexGrow = 1;
            style.justifyContent = Justify.Center;
        }
    }
}
using UnityEngine.UIElements;

namespace Assets.MyUI
{
    [UxmlElement]
    public partial class MyLabel : Label
    {
        public MyLabel()
        {
            selection.doubleClickSelectsWord = false;
            selection.tripleClickSelectsLine = false;
            enableRichText = false;
            displayTooltipWhenElided = false;
        }
    }
}
using R3;
using System;
using System.Collections.Generic;
using UnityEngine.UIElements;

namespace Assets.MyUI
{
    [UxmlElement]
    public partial class MyListView : ListView
    {
        public MyListView()
        {
            // 項目がない時の"List is Empty"を消す
            makeNoneElement = () => null;
        }

        public Observable<IEnumerable<int>> ObservableSelectedIndicesChanged()
        {
            return Observable.FromEvent<IEnumerable<int>>(
                h => selectedIndicesChanged += h,
                h => selectedIndicesChanged -= h);
        }

        public Observable<IEnumerable<int>> ObservableItemAdded()
        {
            return Observable.FromEvent<IEnumerable<int>>(
                h => itemsAdded += h,
                h => itemsAdded -= h);
        }

        public Observable<IEnumerable<int>> ObservableItemRemoved()
        {
            return Observable.FromEvent<IEnumerable<int>>(
                h => itemsRemoved += h,
                h => itemsRemoved -= h);
        }

        public Observable<Unit> ObservableItemsSourceChanged()
        {
            return Observable.FromEvent(
                h => itemsSourceChanged += h,
                h => itemsSourceChanged -= h);
        }

        public Observable<(int oldIndex, int newIndex)> ObservableItemIndexChanged()
        {
            return Observable.FromEvent<Action<int, int>, (int oldIndex, int newIndex)>(
                h => new Action<int, int>((oldIndex, newIndex) => h((oldIndex, newIndex))),
                h => itemIndexChanged += h,
                h => itemIndexChanged -= h);
        }

        public Observable<Unit> ObservableCountModified()
        {
            return Observable.Merge(
                ObservableItemAdded().AsUnitObservable(),
                ObservableItemRemoved().AsUnitObservable()
            );
        }

        public Observable<Unit> ObservableModified()
        {
            return Observable.Merge(
                ObservableItemAdded().AsUnitObservable(),
                ObservableItemRemoved().AsUnitObservable(),
                ObservableItemsSourceChanged(),
                ObservableItemIndexChanged().AsUnitObservable()
            );
        }
    }
}

top

その他の投稿

20260103-01 Unity Entities Tips
20251231-01 Unity UI Toolkit カスタムコントロールサンプル
20250913-01 Unity アプリで Android 16KB ページサイズ確認
20250912-01 Unity 6 で Editor がちらつく問題
20250906-01 Win10サポート終了 ChromeOS Flex を入れてみてつまづいた所
20250812-02 Unity UI Toolkit でのタップ操作検出
20250812-01 Unity UI Toolkit でマップ画面 with RenderTexture
20250811-01 Unity UI Toolkit での座標変換
20250721-01 Unityでカメラが平行投影の場合にScreenToWorldPointがズレる
20250712-01 Unity既存プロジェクトにURP追加