MRが楽しい

MRやVRについて学習したことを書き残す

UniRxのToUniTaskを使って複数ボタンのいずれかの押下を待機する

本日は UniRx の小ネタ枠です。
UniRx の ToUniTask を使って複数ボタンのいずれかの押下を待機する方法を記事にします。

前回記事

本記事は以下の1つのボタンの押下を待機する記事の続きになります。
bluebirdofoz.hatenablog.com

UniRxのToUniTaskを使って複数ボタンのいずれかの押下を待機する

複数のボタンを待機いする場合は Merge を使って IObservable を統合し、その完了を ToUniTask メソッドを使って待機します。

await alphaButton.OnClickAsObservable()
            .Merge(
                betaButton.OnClickAsObservable(),
                gammaButton.OnClickAsObservable()
                )
            .ToUniTask(useFirstValue:true);

どのボタンを押されたかの情報が欲しい場合は Select を使って識別情報を返すなどします。
以下のように複数の ToUniTask のいずれかの完了を待機するように実装してしまうと、押下されなかったボタンの UniTask がメモリリークしてしまうため、IObservable の統合を先に行います。

await UniTask.WhenAny(
    alphaButton.OnClickAsObservable().ToUniTask(useFirstValue:true),
    betaButton.OnClickAsObservable().ToUniTask(useFirstValue:true),
    gammaButton.OnClickAsObservable().ToUniTask(useFirstValue:true)
    )

サンプルスクリプト

以下のサンプルスクリプトを作成しました。
指定したボタンのいずれかのクリックイベントが発生するまで await で待機を行い、押下されたボタンの種類が返ります。
・MultiButtonAwaitTest.cs

using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using UniRx;

public class MultiButtonAwaitTest : MonoBehaviour
{
    [SerializeField]
    private Button alphaButton;
    
    [SerializeField]
    private Button betaButton;
    
    [SerializeField]
    private Button gammaButton;
    
    async void Start()
    {
        Debug.Log("ボタンが押されるまで待機します");
        
        // useFirstValue:trueにすると、OnNextでもawaitの待機が解除される
        // デフォルトまたはuseFirstValue:falseの場合、OnCompleteが来るまで待機が解除されない
        var result = await alphaButton.OnClickAsObservable().Select(_ => "alpha")
            .Merge(
                betaButton.OnClickAsObservable().Select(_ => "beta"),
                gammaButton.OnClickAsObservable().Select(_ => "gamma")
                )
            .ToUniTask(useFirstValue:true);
        
        Debug.Log($"{result}ボタンが押されました");
    }
}

以下のサンプルシーンを用意して Inspector で Button コンポーネントの参照を設定しました。

シーンを再生して動作を確認します。
ボタンを押下すると await が解除され、押下されたボタンの種類がデバッグログで表示されました。