MRが楽しい

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

HoloLens2でホロモンアプリを作る その126(状態変化の判定と変化時の処理をReactivePropertyを使って切り分ける)

本日はアプリ作成枠です。
HoloLens2でホロモンアプリを作る進捗を書き留めていきます。
今回は状態変化の判定と変化時の処理をReactivePropertyを使って切り分ける要処理を見直しました。

基底クラスでReactivePropertyを利用する

今回は以下の記事で検証した動作を基に実装を修正しました。
アイテムオブジェクトで共通の基底クラスに ReactiveProperty で状態を保持するように修正を行いました。
bluebirdofoz.hatenablog.com

シャワーアイテムで状態変化の判定と変化時の処理を切り分ける

一例としてシャワーアイテムでは以下のように状態変化の判定と変化時の処理を切り分けました。
・ItemShowerHeadGimmickAccessAPI.cs

using HoloMonApp.Content.SupportItem.Spawn;
using UnityEngine;
using UnityEngine.Serialization;
using UniRx;

namespace HoloMonApp.Content.SupportItem.Objects.Artifacts.Gimmick.Shower
{
    public class ItemShowerHeadGimmickAccessAPI : BItemArtifactAccessAPI, IItemGenerateTypeAPI
    {
        [Header("状態")]
        [SerializeField, Tooltip("Editor確認用")]
        private ItemShowerHeadGimmickStatus itemShowerHeadGimmickStatus;

        private ItemShowerHeadGimmickStatus GetCastStatus => (ItemShowerHeadGimmickStatus)base.StatusProp.Value;

        [Header("参照")]
        [SerializeField]
        private ItemShowerHeadGimmickBehaveController _itemShowerHeadGimmickBehaveController;
        
        [SerializeField]
        private ItemShowerHeadGimmickStatusChanger _itemShowerHeadGimmickStatusChanger;

        protected override void Start()
        {
            SetStatus(new ItemShowerHeadGimmickStatus(
                ItemShowerHeadGimmickActionType.Neutral,
                ArtifactStatusType.Nothing,
                ContentIdentifyType.ShowerHead));
            
            // 状態の変化を ReactiveProperty で監視する
            // 共通の状態が変化したとき、シャワーアイテム固有のステータス変化に関する処理を行う
            base.StatusProp
                .Subscribe(state =>
                {
                    itemShowerHeadGimmickStatus = (ItemShowerHeadGimmickStatus)state;
                    _itemShowerHeadGimmickStatusChanger.ChangeStatus(
                        itemShowerHeadGimmickStatus.GetItemShowerHeadGimmickActionType());
                })
                .AddTo(this);

            base.Start();
        }

        public override void SpawnObject()
        {
            base.SpawnObject();
        }
        
        public override void DestroyObject()
        {
            base.DestroyObject();
        }

        public void SetItemSpawnAPI(ItemSpawnAPI itemSpawnAPI)
        {
            _itemShowerHeadGimmickBehaveController.SetItemSpawnAPI(itemSpawnAPI);
        }

        // プレイヤーのアイテム掴み時処理
        public void SetShowerTrigger(bool onoff)
        {
            // アイテムが掴まれたとき、水流をだす状態と判定する
            // 状態の変化を受け取って ReactiveProperty に反映する
            ItemShowerHeadGimmickActionType type =
                onoff ? ItemShowerHeadGimmickActionType.ShootWater : ItemShowerHeadGimmickActionType.Neutral;
            SetStatus(GetCastStatus.WithItemShowerHeadGimmickActionType(type));
        }
    }
}

・BContentAccessAPI.cs(アイテム共通の基底クラス)

using System;
using HoloMonApp.Content.Character.Data.Knowledge.Objects;
using UniRx;
using UnityEngine;
using UnityEngine.Serialization;

namespace HoloMonApp.Content
{
    public abstract class BContentAccessAPI : MonoBehaviour
    {
        /// <summary>
        /// アイテム状態
        /// </summary>
        private ReactiveProperty<BContentStatus> _statusPropProp = new();

        protected IReadOnlyReactiveProperty<BContentStatus> StatusProp => _statusPropProp;
        protected void SetStatus(BContentStatus status) => _statusPropProp.Value = status;

        // (略)
    }
}

アイテムの掴み処理は MRTK のコンポーネントから呼び出します。

シーンを再生してシャワーを掴むと、状態が切り替わり、シャワーから水が発射されました。
現在の状態が切り替わったことは Inspector ビューからも確認できます。

アイテムの処理実行時には必ずアイテムの状態変更を経由するため、今後シェアリングの実装時に状態の同期がとりやすくなります。