MRが楽しい

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

HoloLens2でホロモンアプリを作る その69(ホロモンアプリにシャワーヘッドをアイテムとして追加する)

本日はアプリ作成枠です。
HoloLens2でホロモンアプリを作る進捗を書き留めていきます。
f:id:bluebirdofoz:20211109234235j:plain

今回はホロモンアプリにシャワーヘッドをアイテムとして追加するメモです。

シャワーヘッドを追加する

今回は以下の記事で作成したシャワーヘッドをホロモンアプリに追加します。
bluebirdofoz.hatenablog.com

プレハブ化したオブジェクトとアセットをホロモンアプリにそのままコピーしました。
f:id:bluebirdofoz:20211109234255j:plain

シーンに配置して動作確認してみたところ、特に問題なく動作しました。
f:id:bluebirdofoz:20211109234304j:plain

アイテムの呼び出し処理の追加

ホロモンアプリではボタンUIから呼び出したときのみ、シャワーヘッドを表示したいので呼び出し処理は新たに実装します。
f:id:bluebirdofoz:20211109234312j:plain

シャワーヘッドを配置する台を含めてリスポーンするための以下のスクリプトを作成しました。
・ItemHandShowerHeadController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using System;

using HoloMonApp.ConditionSpace;

namespace HoloMonApp.ItemSpace
{
    public class ItemHandShowerHeadController : MonoBehaviour
    {
        [Serializable]
        private class ChildObjectData
        {
            public GameObject Object;
            public Vector3 DefaultLocalPosition;
            public Quaternion DefaultLocalRotation;
        }

        /// <summary>
        /// コントロール対象
        /// </summary>
        [SerializeField, Tooltip("コントロール対象")]
        private GameObject p_ControlObject;

        /// <summary>
        /// デフォルト座標
        /// </summary>
        [SerializeField, Tooltip("デフォルト座標")]
        private Vector3 p_DefaultWorldPosition;

        /// <summary>
        /// デフォルトサイズ
        /// </summary>
        [SerializeField, Tooltip("デフォルトサイズ")]
        private Vector3 p_DefaultLocalScale;

        /// <summary>
        /// 現在のスケール変化比率
        /// </summary>
        [SerializeField, Tooltip("現在のスケール変化比率")]
        private float p_ScaleRatio;

        /// <summary>
        /// スポーン位置
        /// </summary>
        [SerializeField, Tooltip("スポーン位置")]
        private Transform p_SpawnPosition;

        /// <summary>
        /// 管理子オブジェクトリスト
        /// </summary>
        [SerializeField, Tooltip("管理子オブジェクトリスト")]
        private List<ChildObjectData> p_ChildObjectDataList;

        /// <summary>
        /// 開始処理
        /// </summary>
        void Start()
        {
            // デフォルト座標を保存
            p_DefaultWorldPosition = p_ControlObject.transform.position;

            // デフォルトスケールを保存
            p_DefaultLocalScale = p_ControlObject.transform.localScale;

            // 子オブジェクトのデフォルト情報を保存
            SaveChildObjectData();
        }

        /// <summary>
        /// 定期処理
        /// </summary>
        void Update()
        {

        }

        /// <summary>
        /// スポーン状態を切り替える
        /// </summary>
        public void SpawnSwitch()
        {
            if (p_ControlObject.activeSelf)
            {
                // 子オブジェクトの状態をデフォルトに戻す
                ApplyChildObjectData();

                // デフォルト位置に戻す
                p_ControlObject.transform.position = p_DefaultWorldPosition;

                // オブジェクトを無効化する
                p_ControlObject.SetActive(false);
            }
            else
            {
                // 子オブジェクトの状態をデフォルトに戻す
                ApplyChildObjectData();

                // オブジェクトを有効化する
                p_ControlObject.SetActive(true);

                // スポーン位置にオブジェクトを移動する
                p_ControlObject.transform.position = p_SpawnPosition.position;

                // オブジェクトは水平に配置する
                p_ControlObject.transform.eulerAngles = new Vector3(0.0f, p_SpawnPosition.eulerAngles.y, 0.0f);

                // 子オブジェクトのアクティブを確認して有効化する
                ActiveChildObjectData();
            }
        }

        /// <summary>
        /// 子オブジェクトのデータを保存する
        /// </summary>
        private void SaveChildObjectData()
        {
            foreach (ChildObjectData objectData in p_ChildObjectDataList)
            {
                objectData.DefaultLocalPosition = objectData.Object.transform.localPosition;
                objectData.DefaultLocalRotation = objectData.Object.transform.localRotation;
            }
        }

        /// <summary>
        /// 子オブジェクトのデータを再反映する
        /// </summary>
        private void ApplyChildObjectData()
        {
            foreach (ChildObjectData objectData in p_ChildObjectDataList)
            {
                // オブジェクトに慣性コンポーネントがある場合は慣性を無効化しておく
                Rigidbody rigid = objectData.Object.GetComponent<Rigidbody>();
                if (rigid != null) rigid.velocity = Vector3.zero;

                objectData.Object.transform.localPosition = objectData.DefaultLocalPosition;
                objectData.Object.transform.localRotation = objectData.DefaultLocalRotation;
            }
        }

        /// <summary>
        /// 子オブジェクトのアクティブを確認して有効化する
        /// </summary>
        private void ActiveChildObjectData()
        {
            foreach (ChildObjectData objectData in p_ChildObjectDataList)
            {
                if (!objectData.Object.activeSelf) objectData.Object.SetActive(true);
            }
        }
    }
}

作成したスクリプトを親オブジェクトに設定しました。
f:id:bluebirdofoz:20211109234329j:plain

ボタンUIから本スクリプトの SpawnSwitch() 関数を呼び出して、シャワーヘッドを表示します。
f:id:bluebirdofoz:20211109234340j:plain

動作確認

シーンを再生して動作を確認します。
f:id:bluebirdofoz:20211109234351j:plain

ボタンUIを押すと、ハンドメニューの近くにシャワーヘッドがスポーンします。
f:id:bluebirdofoz:20211109234359j:plain

スポーンしたシャワーヘッドを掴むと水が流れ出てきました。
f:id:bluebirdofoz:20211109234408j:plain