79 lines
3.6 KiB
C#
79 lines
3.6 KiB
C#
using UnityEngine;
|
||
|
||
// World Space Canvas をプレイヤーの真正面に移動させ、開いている間はプレイヤーの視点に滑らかに追従させるスクリプト
|
||
public class VRUIDoorFaceFollow : MonoBehaviour
|
||
{
|
||
[SerializeField] private Transform vrCameraTransform;
|
||
|
||
[Header("配置・追従のパラメータ")]
|
||
[SerializeField] private float forwardDistance = 0.5f;
|
||
[SerializeField] private float heightOffset = -0.1f;
|
||
[SerializeField] private float followSpeed = 5.0f;
|
||
|
||
// 画面がアクティブ(表示)になった瞬間を検知するためのフラグ
|
||
private bool wasActiveLastFrame = false;
|
||
|
||
private void Start()
|
||
{
|
||
// カメラが未設定の場合は、シーン内からメインカメラを自動取得
|
||
if (vrCameraTransform == null && Camera.main != null)
|
||
{
|
||
vrCameraTransform = Camera.main.transform;
|
||
}
|
||
}
|
||
|
||
// 全体の時間が止まっている(Time.timeScale = 0)間でも動作させるため、カメラ移動の後に実行される LateUpdate を使用します
|
||
private void LateUpdate()
|
||
{
|
||
if (vrCameraTransform == null) return;
|
||
|
||
// このオブジェクト(UI画面)が有効化された「最初のフレーム」の処理
|
||
if (!wasActiveLastFrame)
|
||
{
|
||
// 開いた瞬間は、プレイヤーの今の向きの「完全な正面」に瞬間移動させる(遅れてついてくるのを防ぐため)
|
||
SetInitialPosition();
|
||
wasActiveLastFrame = true;
|
||
return;
|
||
}
|
||
|
||
// 毎フレームの滑らかな追従処理
|
||
SmoothFollowPlayer();
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
// 画面が閉じられたらフラグをリセットする
|
||
wasActiveLastFrame = false;
|
||
}
|
||
|
||
/// 画面が開いた瞬間に、プレイヤーの正面の正しい位置・向きに強制配置する
|
||
private void SetInitialPosition()
|
||
{
|
||
// カメラの位置から、カメラが向いている正面方向に一定距離進んだ座標を計算
|
||
Vector3 targetPosition = vrCameraTransform.position + (vrCameraTransform.forward * forwardDistance);
|
||
targetPosition.y += heightOffset; // 高さを微調整
|
||
|
||
transform.position = targetPosition;
|
||
|
||
// 画面の向きをプレイヤー(カメラ)の方向に向ける(背を向けないようにする)
|
||
// UIパネルがプレイヤー側を正面にするよう、LookAtの後に180度回転させて裏返りを防ぎます
|
||
transform.LookAt(vrCameraTransform.position);
|
||
transform.Rotate(0, 180, 0);
|
||
}
|
||
|
||
/// プレイヤーが首を動かしたり移動したりした際、画面を滑らかについてこさせる
|
||
private void SmoothFollowPlayer()
|
||
{
|
||
// 目的地(目標座標)の計算
|
||
Vector3 targetPosition = vrCameraTransform.position + (vrCameraTransform.forward * forwardDistance);
|
||
targetPosition.y += heightOffset;
|
||
|
||
// Time.timeScale = 0 でも動かすため、Time.unscaledDeltaTime を使用
|
||
// 現在位置から目標位置まで滑らかに補間移動(Lerp)させる
|
||
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.unscaledDeltaTime * followSpeed);
|
||
|
||
// 向きも滑らかに補間(Slerp)してプレイヤーの方を向かせ続ける
|
||
Quaternion targetRotation = Quaternion.LookRotation(transform.position - vrCameraTransform.position);
|
||
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.unscaledDeltaTime * followSpeed);
|
||
}
|
||
} |