MRが楽しい

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

HoloLens2でホロモンアプリを作る その115(メインメニューのボタン操作をスクリプトで管理する)

本日はアプリ作成枠です。
HoloLens2でホロモンアプリを作る進捗を書き留めていきます。
今回はメインメニューのボタン操作をスクリプトで管理する修正を行いました。

ボタン操作をスクリプトで管理する

今回はこれまで Inspector の OnClick で管理していたボタンイベントをスクリプトで管理する形に修正しました。
スクリプトで OnClick の処理を管理することで処理の動的な差し替えや処理の流れの追跡がよりやりやすくなります。
MRTK のボタンをスクリプトで管理する方法の詳細は以下の記事を参照ください。
bluebirdofoz.hatenablog.com

育成メニューのボタン操作を管理するスクリプト

以下の育成メニューを管理するスクリプトを作成しました。

育成メニューにはメニュー自体の参照情報の変更やホロモンのステータス参照、アイテムの出現など様々な効果を持つボタンが集約しています。
スクリプトでは以下の通り、様々な参照クラスを経由してボタンの処理を呼び出す形にしています。
Inspector でイベントを設定していた場合に比べて、動的に参照先を差し替えれるほか、ボタンからどの処理を呼び出しているか何のクラスを参照しているかが追跡しやすくなりました。
・BreedingPanelControlAPI.cs

using System;
using Cysharp.Threading.Tasks;
using HoloMonApp.Content.Character.Access;
using HoloMonApp.Content.SupportItem.Spawn;
using Microsoft.MixedReality.Toolkit.UI;
using UniRx;
using UnityEngine;
using UnityEngine.Serialization;

namespace HoloMonApp.Content.SupportItem.Objects.Windows.BreedingMenuWindow.MainMenu.Panels
{
    public class BreedingPanelControlAPI : PanelControlAPIBase
    {
        [SerializeField] private Interactable statusButton;
        [SerializeField] private Interactable foodButton;
        [SerializeField] private Interactable ballButton;
        [SerializeField] private Interactable toiletButton;
        [SerializeField] private Interactable cleanButton;
        [SerializeField] private Interactable comeButton;
        [SerializeField] private Interactable stayButton;
        [SerializeField] private Interactable revertButton;

        private IDisposable statusButtonDisposable;
        private IDisposable foodButtonDisposable;
        private IDisposable ballButtonDisposable;
        private IDisposable toiletButtonDisposable;
        private IDisposable cleanButtonDisposable;
        private IDisposable comeButtonDisposable;
        private IDisposable stayButtonDisposable;
        private IDisposable revertButtonDisposable;

        public void RefreshUI(
            ItemBreedingMenuWindowAccessAPI itemBreedingMenuWindowAccessAPI,
            HoloMonAccessAPI holomonAccessAPI,
            ItemSpawnAPI itemSpawnAPI,
            ItemBreedingMenuWindowSettings itemBreedingMenuWindowSettings)
        {
            if (statusButtonDisposable != null) statusButtonDisposable.Dispose();
            if (foodButtonDisposable != null) foodButtonDisposable.Dispose();
            if (ballButtonDisposable != null) ballButtonDisposable.Dispose();
            if (toiletButtonDisposable != null) toiletButtonDisposable.Dispose();
            if (cleanButtonDisposable != null) cleanButtonDisposable.Dispose();
            if (comeButtonDisposable != null) comeButtonDisposable.Dispose();
            if (statusButtonDisposable != null) statusButtonDisposable.Dispose();
            if (revertButtonDisposable != null) revertButtonDisposable.Dispose();

            // ちょうしボタンの設定
            if (itemBreedingMenuWindowAccessAPI != null)
            {
                statusButtonDisposable = statusButton.OnClick.AsObservable()
                    .Subscribe(_ =>
                    {
                        itemBreedingMenuWindowAccessAPI.ChangeStatus(ItemBreedingMenuWindowStatus.BodyStatus);
                    })
                    .AddTo(this);
                statusButton.IsEnabled = true;
            }
            else
            {
                statusButton.IsEnabled = false;
            }
            
            // おにくボタンの設定
            if (itemSpawnAPI != null)
            {
                foodButtonDisposable = foodButton.OnClick.AsObservable()
                    .Subscribe(_ =>
                    {
                        Pose spawnPose = new Pose(
                            itemBreedingMenuWindowSettings.ItemSpawnTargetTransform.position,
                            itemBreedingMenuWindowSettings.ItemSpawnTargetTransform.rotation
                        );
                        itemSpawnAPI.SpawnItemMeatFood(spawnPose);
                    })
                    .AddTo(this);
                foodButton.enabled = true;
            }
            else
            {
                foodButton.enabled = false;
            }
            
            // おもちゃボタンの設定
            if (itemSpawnAPI != null)
            {
                Pose spawnPose = new Pose(
                    itemBreedingMenuWindowSettings.ItemSpawnTargetTransform.position,
                    itemBreedingMenuWindowSettings.ItemSpawnTargetTransform.rotation
                );
                itemSpawnAPI.SpawnItemBallToy(spawnPose);
                ballButton.enabled = true;
            }
            else
            {
                ballButton.enabled = false;
            }
            
            // ながすボタンの設定
            if (itemSpawnAPI != null)
            {
                Pose spawnPose = new Pose(
                    itemBreedingMenuWindowSettings.ItemSpawnTargetTransform.position,
                    itemBreedingMenuWindowSettings.ItemSpawnTargetTransform.rotation
                );
                itemSpawnAPI.SpawnItemShowerHeadGimmick(spawnPose);
                toiletButton.enabled = true;
            }
            else
            {
                toiletButton.enabled = false;
            }
            
            // かたづけボタンの設定
            if (itemSpawnAPI != null)
            {
                itemSpawnAPI.CleanAllItem();
                cleanButton.enabled = true;
            }
            else
            {
                cleanButton.enabled = false;
            }
            
            // おいでボタンの設定
            if (holomonAccessAPI != null)
            {
                comeButtonDisposable = comeButton.OnClick.AsObservable()
                    .Subscribe(_ =>
                    {
                        holomonAccessAPI.InterruptCommands.StartComeHere();
                    })
                    .AddTo(this);
                comeButton.enabled = true;
            }
            else
            {
                comeButton.enabled = false;
            }
            
            // まてボタンの設定
            if (holomonAccessAPI != null)
            {
                statusButtonDisposable = stayButton.OnClick.AsObservable()
                    .Subscribe(_ =>
                    {
                        holomonAccessAPI.InterruptCommands.StartWait();
                    })
                    .AddTo(this);
                stayButton.enabled = true;
            }
            else
            {
                stayButton.enabled = false;
            }
            
            // もどるボタンの設定
            if (holomonAccessAPI != null)
            {
                revertButtonDisposable = revertButton.OnClick.AsObservable()
                    .Subscribe(_ =>
                    {
                        var position = itemBreedingMenuWindowSettings.CharacterSpawnTargetTransform;
                        holomonAccessAPI.InterruptCommands.ResetPosition(position);
                    })
                    .AddTo(this);
                revertButton.enabled = true;
            }
            else
            {
                revertButton.enabled = false;
            }
        }
    }
}