MRが楽しい

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

HoloLens2でホロモンアプリを作る その73(ホロモンアプリに段ボール箱をアイテムとして追加する)

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

今回はホロモンアプリに段ボール箱をアイテムとして追加したメモです。

段ボール箱を追加する

今回は以下の記事で作成した段ボール箱をホロモンアプリに追加します。
bluebirdofoz.hatenablog.com

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

シーンに配置して動作確認してみたところ、問題なく蓋を開ける動作も機能しました。
f:id:bluebirdofoz:20211122232633j:plain

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

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

段ボール箱を配置する台を含めてリスポーンするための以下のスクリプトを作成しました。
・ItemHandCardboardBoxController.cs

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

using UniRx;

using HoloMonApp.ConditionSpace;

namespace HoloMonApp.ItemSpace
{
    public class ItemHandCardboardBoxController : 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:20211122232717j:plain

ボタンUIから本スクリプトの SpawnSwitch() 関数を呼び出して、段ボール箱を再配置して表示します。
f:id:bluebirdofoz:20211122232733j:plain

動作確認

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

ボタンUIを押すと、ハンドメニューの近くに段ボール箱がスポーンします。
f:id:bluebirdofoz:20211122232758j:plain

段ボール箱にはホロモンを入れてあげることができます。ホロモンのための簡易ベッドです。
f:id:bluebirdofoz:20211122232809j:plain