MRが楽しい

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

HoloLens2でホロモンアプリを作る その49(ホロモンアプリの言霊アニメーションを時間経過の演出に修正する)

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

今回はホロモンアプリの言霊アニメーションを時間経過の演出に修正するメモです。

言霊アニメーション

以前の記事で、ホロモンに会話したときのアニメーションとしてプレイヤーの位置からホロモンに言霊のようなものを都バスアニメーションを作成しました。
bluebirdofoz.hatenablog.com

問題点と修正

このときの実装では目的座標に到達するための Lerp 関数の経過でフレームによる係数増加を行っていました。
この実装では、負荷の軽い Unity エディター上の動作と HoloLens2 上で負荷がかかった際の動作で時間当たりのフレーム数が異なるため、到達までの時間に差が発生する問題が起こります。

負荷にかかわらず、演出が一定時間で完了するように Lerp 関数の係数を時間経過で設定するようにしました。
・RotateAroundTargetGravitation.cs

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

using System;

namespace BreakBubble
{
    public class RotateAroundTargetGravitation : MonoBehaviour
    {
        /// <summary>
        /// 移動完了時イベント
        /// </summary>
        public Action MoveEndEvent;

        [Tooltip("開始位置オブジェクト")]
        public GameObject StartObject;

        [Tooltip("ターゲットオブジェクト")]
        public GameObject TargetObject;

        [Tooltip("開始時の回転速度係数")]
        public float SpeedFactor;

        [Tooltip("到達までの秒数")]
        public float LerpTime;

        /// <summary>
        /// 現在の経過時間
        /// </summary>
        private float timeElapsed;

        /// <summary>
        /// 開始時の2点間の距離
        /// </summary>
        private float p_RadiusDistance;

        /// <summary>
        /// 回転軸
        /// </summary>
        private Vector3 p_RotateAxis;

        /// <summary>
        /// 移動中フラグ
        /// </summary>
        private bool p_MoveFlg;

        private void Start()
        {
            // 回転軸はY軸(縦軸)に固定する
            p_RotateAxis = Vector3.up;
        }

        // Update is called once per frame
        void Update()
        {
            if (!p_MoveFlg) return;

            // 設定が不足している場合は処理しない
            if (StartObject == null || TargetObject == null ||
                SpeedFactor <= 0.0f || LerpTime <= 0.0f) return;

            // 経過時間を記録する
            timeElapsed += Time.deltaTime;

            // 各オブジェクト位置を取得する
            Vector3 targetPosition = TargetObject.transform.position;
            Vector3 selfPosition = this.transform.position;

            // 現在の距離を取得する
            float currentRadiusDistance = Vector3.Distance(selfPosition, targetPosition);

            if (Vector3.Distance(targetPosition, selfPosition) < 0.05f)
            {
                // 移動終了イベントを呼び出し
                MoveEndEvent?.Invoke();
                p_MoveFlg = false;
                return;
            }

            // 距離が近づくほど回転速度を早くする
            float currentSpeedFactor = (SpeedFactor * Time.deltaTime) * (p_RadiusDistance / currentRadiusDistance);

            // Leap 関数を使って時間経過で徐々にターゲットに近づいていく
            this.transform.position = Vector3.Lerp(selfPosition, targetPosition, (timeElapsed / LerpTime));

            // 指定オブジェクトを中心に回転する
            this.transform.RotateAround(
                targetPosition,
                p_RotateAxis,
                360.0f / (1.0f / currentSpeedFactor) * Time.deltaTime
                );
        }

        public bool MoveStart()
        {
            // 既に実行中の場合は開始しない
            if (p_MoveFlg) return false;

            // 設定が不足している場合は開始しない
            if (StartObject == null || TargetObject == null ||
                SpeedFactor <= 0.0f || LerpTime <= 0.0f) return false;

            // 各オブジェクト位置を取得する
            Vector3 startPosition = StartObject.transform.position;
            Vector3 targetPosition = TargetObject.transform.position;

            // 初期位置はスタートオブジェクトと同じ位置に設定する
            this.transform.position = startPosition;

            // 開始時の距離を取得する
            p_RadiusDistance = Vector3.Distance(startPosition, targetPosition);

            // 経過時間をリセットする
            timeElapsed = 0.0f;

            // 移動中フラグをONにする
            p_MoveFlg = true;

            return true;
        }
    }
}

f:id:bluebirdofoz:20210731232236j:plain

動作確認

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

Unity エディター上での動作と HoloLens2 での動作で言霊の到達スピードが同じになるようになりました。
f:id:bluebirdofoz:20210731232257j:plain