📗
【Unity】UniRxで自作のカスタムボタンを作ろう
はじめに
初めての方も、そうでない方もこんにちは!
現役ゲームプログラマーのたむぼーです。
自己紹介を載せているので、気になる方は見ていただければ嬉しいです!
今回は
UniRxでUnityのカスタムボタン
の作り方を紹介します
補足
アニメーション管理はこちらを使ってます
合わせて使ってみてください~
Unity標準ボタンではダメ?
UnityのUIにある、Unity標準ボタンでは機能不足になることが多く、
初めの設計を間違うと、あとあと大規模改修・・・コンポーネント張り替え地獄がまってます
そうならないためにも、初めの設計(特にボタン)は重要です
Unity標準ボタンは機能不足
Unity標準ボタンの機能は約3種類扱えない
Unity標準ボタンは拡張できない
標準ボタンをラップしてできるが、それでも標準ボタンとは違うコンポーネントになるので、拡張ができない(しない)と考えてもいい思います
Unity標準ボタンはボタン処理を一括修正ができない
標準ボタンは機能を拡張できないから、処理の一括修正もできません
Unity標準ボタンはInspectorから関数を設定できる
便利じゃん?と思うかもしれませんが、これの問題点・・・
それは、プログラム側で読み取れないこと
あれ、ボタンのクリック処理おかしい・・けど、処理はあってるな?状態になる
カスタムボタンとは・・・
MonoBehaviourクラスと、各イベントのIPointer〇〇と付くインターフェースを継承して実装します。
public class ButtonEx : MonoBehaviour,
IPointerClickHandler,
IPointerDownHandler,
IPointerUpHandler
{
}
実際の処理
こちらは、クリック時、ボタンが押された時、ボタンが離された時の状態を扱えるようになってます。
必要に応じて拡張、改変してください
カスタムボタン
ButtonEx.cs
using System;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UniRx;
namespace Utils
{
public class ButtonEx : MonoBehaviour,
IPointerClickHandler,
IPointerDownHandler,
IPointerUpHandler
{
[Header("ボタン設定")]
[SerializeField]
private bool _isInteractable = true;
[SerializeField]
private Color32 _disabledColor = new Color32(255, 255, 255, 128);
[Header("アニメーション設定")]
[SerializeField]
private string _pointerDownStateName = "PointerDown";
[SerializeField]
private string _pointerUpStateName = "PointerUp";
private Image _image;
private Animator _animator;
private Color32 _defaultColor;
private bool _isClickSubscribers = false;
private bool _isPointerDownSubscribers = false;
private bool _isPointerUpSubscribers = false;
// Subject関連
private readonly Subject<Unit> _onClickSubject = new Subject<Unit>();
private readonly Subject<Unit> _onPointerDownSubject = new Subject<Unit>();
private readonly Subject<Unit> _onPointerUpSubject = new Subject<Unit>();
/// <summary> デバウンスのミリ秒 </summary>
private const int dueMilliseconds = 500;
/// <summary>
/// 開始時
/// </summary>
private void Start()
{
_image = GetComponent<Image>();
_animator = GetComponent<Animator>();
_defaultColor = _image.color;
}
/// <summary>
/// 破壊時
/// </summary>
private void OnDestroy()
{
_onClickSubject?.Dispose();
_onPointerDownSubject?.Dispose();
_onPointerUpSubject?.Dispose();
}
/// <summary>
/// クリックしたときイベント
/// </summary>
public IObservable<Unit> OnClickAsObservable()
{
_isClickSubscribers = true;
return _onClickSubject.AsObservable().ThrottleFirst(TimeSpan.FromMilliseconds(dueMilliseconds));
}
/// <summary>
/// 押されたときのイベント
/// </summary>
public IObservable<Unit> OnPointerDownAsObservable()
{
_isPointerDownSubscribers = true;
return _onPointerDownSubject.AsObservable();
}
/// <summary>
/// 離されたときのイベント
/// </summary>
public IObservable<Unit> OnPointerUpAsObservable()
{
_isPointerUpSubscribers = true;
return _onPointerUpSubject.AsObservable();
}
/// <summary>
/// 有効状態の設定
/// </summary>
public void SetInteractable(bool isInteractable)
{
_isInteractable = isInteractable;
SetColor(_isInteractable ? _defaultColor : _disabledColor);
}
/// <summary>
/// 押されたときのアニメーションを変更
/// </summary>
public void SetPointerDownStateName(string stateName)
{
_pointerDownStateName = stateName;
}
/// <summary>
/// 離されたときのアニメーションを変更
/// </summary>
public void SetPointerUpStateName(string stateName)
{
_pointerUpStateName = stateName;
}
/// <summary>
/// クリック
/// </summary>
public void OnPointerClick(PointerEventData eventData)
{
if (_isInteractable)
{
if (_isClickSubscribers)
{
_onClickSubject.OnNext(Unit.Default);
}
}
}
/// <summary>
/// 押した
/// </summary>
public void OnPointerDown(PointerEventData eventData)
{
if (_isInteractable)
{
if (_isPointerDownSubscribers)
{
_onPointerDownSubject.OnNext(Unit.Default);
}
AnimationManager.Instance.AddAnimationObject(gameObject, _pointerDownStateName, _animator);
}
}
/// <summary>
/// 離した
/// </summary>
public void OnPointerUp(PointerEventData eventData)
{
if (_isInteractable)
{
if (_isPointerUpSubscribers)
{
_onPointerUpSubject.OnNext(Unit.Default);
}
AnimationManager.Instance.AddAnimationObject(gameObject, _pointerUpStateName, _animator);
}
}
/// <summary>
/// 色変更
/// </summary>
private void SetColor(Color32 color)
{
if (_image != null)
{
_image.color = color;
}
}
}
}
使用例
using UniRx;
using UnityEngine;
using Utils;
public class Example : MonoBehaviour
{
[SerializeField]
private ButtonEx _button;
private void Start()
{
// ボタンクリック時の処理
_button.OnClickAsObservable().Subscribe(_ => OnClick()).AddTo(this);
}
private void OnClick()
{
Debug.Log("ボタンクリック時に実行したい処理");
}
}
Discussion