UnityでDialog Boxを表示する(3)


はじめに

「UnityでDialog Boxを表示する(2)」では、OKボタンを付けたDialog Boxを作成しました。これで、WindowsのDialog Boxに似てきたと思いますが、Dialog Boxに”Yes”、”No”ボタンがあるタイプのDialog Boxも良く見かけます。このDialog Boxは2つのボタンのどちらが押されたかが分かり、その後の処理を変更することができます。そこで今回は、この”Yes”、”No”ボタンが付いたDialog Box(Dialog Box YesNo)を紹介させて頂きます。

デザイン

前回のDialog Boxにボタンを1つ加えて、ボタンの表示を”Yes”と”No”に変更しました。メッセージが表示された後、”Yes”または”No”ボタンを押すとDialog Boxが消えます。また、どちらのボタンが押されたかも分かります。

図1.デザイン

このDialog Boxの表示のためのUnity Hierarchyを以下のようにしました。

図2.Hierarchy

図2のPanelMessageYesNo以下が2つのボタンの付いたDialog Box YesNoです。

以下は、このDialog Box YesNoのスクリプトです。今回は、ボタンが押されるのを待ったうえで、押されたボタンを判定しなくてはなりません。段々とコードが難しくなってきますし、実現方法も色々と考えられます。今回は、実現が容易でこれまでのDialog Boxと似たような利用方法が実現されることをもくひょうとしてみました。重要な点は、Yes/Noのどちらが押されたかはPublic Resultで調べるという実装です。Show()メソッドを呼ぶ前でもResultの値を得ることができてしまいます。そこで使い方にも工夫が必要ですが、それは利用例のコードで説明します。

using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;

public class DialogBoxYesNoScript : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI _messageText;
    [SerializeField] private Button _yesButton;
    [SerializeField] private Button _noButton;
    private bool _isAnswered = false;
    public bool Result { private set; get; }    // Yes = true, No = false

    void OnEnable()
    {
        _isAnswered = false;
        Result = false;
    }

    /// <summary>
    /// Yes/Noダイアログを表示し、ユーザーの選択を待ちます。
    /// </summary>
    /// <param name="message">表示するメッセージ</param>
    /// <param name="error">エラー表示にする場合はtrue(赤字)</param>
    public IEnumerator Show(string message, bool error = false)
    {
        _isAnswered = false;
        Result = false;

        // メッセージ設定
        _messageText.text = message;
        _messageText.color = error ? Color.red : Color.white;

        // 表示
        gameObject.SetActive(true);

        // 以前のリスナーを削除
        _yesButton.onClick.RemoveAllListeners();
        _noButton.onClick.RemoveAllListeners();

        // Yesボタン設定
        _yesButton.onClick.AddListener(() =>
        {
            //Debug.Log("[Dialog] YES pressed");
            Result = true;
            _isAnswered = true;
            gameObject.SetActive(false);
        });

        // Noボタン設定
        _noButton.onClick.AddListener(() =>
        {
            //Debug.Log("[Dialog] NO pressed");
            Result = false;
            _isAnswered = true;
            gameObject.SetActive(false);
        });

        // ボタン押下まで待機
        yield return new WaitUntil(() => _isAnswered);
    }
}

動作確認

実際にアプリケーションにどう組み込むかは本コードを参考にしてください。重要な点ShowDialogBox()で、_dialog.Show()が完了しないとyield return以下が実行されず、完了後に初めて_dialog.Resultが評価される点です。ここは非同期処理ならではの点ですね。非同期処理に関しては別の機会に説明します。また、様々な非同期処理のソースコードを作成できるようになってくると以下の例以外にも実装方法が沢山あることが分かるようになります。

using System.Collections;
using UnityEngine;

public class DialogBox3TestScript : MonoBehaviour
{
    [SerializeField] private DialogBoxYesNoScript _dialog;
    private InputSystem_Actions _input;
    
    void Awake()
    {
        _input = new InputSystem_Actions();
    }
    void Start() { }

    void Update() { }

    private void OnEnable()
    {
        _input.Enable();
        _input.Player.Button3.performed += ctx => ShowDialogBox3();
    }

    private void ShowDialogBox3()
    {
        Debug.Log("button3");
        StartCoroutine(ShowDialogBox());
    }

    private IEnumerator ShowDialogBox()
    {
        yield return StartCoroutine(_dialog.Show("Yes No ボタン付きダイアログボックス", true));

        if (_dialog.Result) Debug.Log("Yes");
        else Debug.Log("No");
    }
}

 図3が動作結果です。YesまたはNoボタンを押すとDialog Boxが消えます。また、その結果をResultで得ることができます。

図3.実行結果

コメントを残す

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

PAGE TOP