Files
VRProject/Assets/Scripts/ElevatorSceneTransition.cs
2026-06-15 16:17:09 +09:00

130 lines
5.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityEngine.XR; // 振動機能のために必要
using System.Collections;
public class ElevatorSceneTransition : MonoBehaviour
{
[Header("遷移先の設定")]
[SerializeField] private string bossSceneName = "BossStage";
[SerializeField] private string playerTag = "Player";
[Header("ローディングUI設定")]
[SerializeField] private GameObject loadingCanvas;
[SerializeField] private Text progressText;
[SerializeField] private Slider progressSlider;
// ─── ★ここから下降演出用の設定項目を追加 ───
[Header("エレベーター下降演出設定")]
[Tooltip("エレベーターの部屋壁や床、UIすべてをまとめている一番親のTransformを指定してください")]
[SerializeField] private Transform elevatorCageTransform;
[Tooltip("ガタガタ揺れる激しさミリ単位。0.010.03あたりがVR酔いしにくく自然です")]
[SerializeField] private float shakeMagnitude = 0.015f;
[Tooltip("下降中のコントローラーの振動の強さ0.0 1.0")]
[SerializeField] private float hapticAmplitude = 0.15f;
// ─────────────────────────────────────────
private bool isLoadingStarted = false;
private Vector3 originalCagePosition; // 揺らす前のエレベーターの初期位置を記憶する用
private void Start()
{
if (loadingCanvas != null)
{
loadingCanvas.SetActive(false);
}
// 部屋の初期位置を保存
if (elevatorCageTransform != null)
{
originalCagePosition = elevatorCageTransform.localPosition;
}
}
private void OnTriggerEnter(Collider other)
{
if (isLoadingStarted) return;
if (other.CompareTag(playerTag))
{
isLoadingStarted = true;
Debug.Log("🛗 プレイヤー乗車:下降演出と非同期ロードを開始します。");
StartCoroutine(LoadSceneAsyncRoutine());
}
}
private IEnumerator LoadSceneAsyncRoutine()
{
if (loadingCanvas != null) loadingCanvas.SetActive(true);
// 次のシーンの非同期ロードを開始(画面切り替えはまだロックする)
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(bossSceneName);
asyncLoad.allowSceneActivation = false;
// コントローラーの振動のタイミングを計るためのタイマー
float hapticTimer = 0f;
// ロード中progressが0.9未満の間)、ずっとループして演出を実行
while (asyncLoad.progress < 0.9f)
{
// 1. UIの進捗率を更新
float currentProgress = Mathf.Clamp01(asyncLoad.progress / 0.9f);
if (progressText != null) progressText.text = $"LOADING: {(currentProgress * 100f):F0}%";
if (progressSlider != null) progressSlider.value = currentProgress;
// 2. 【演出:部屋をガタガタ揺らす】
// 初期位置をベースに、毎フレームごくわずかなランダム座標を計算して部屋を揺らす
if (elevatorCageTransform != null)
{
Vector3 randomOffset = Random.insideUnitSphere * shakeMagnitude;
// ※左右前後のブレX, Zのみを揺らし、Y上下はあえて固定すると「ガタガタ感」が出ます
randomOffset.y = 0;
elevatorCageTransform.localPosition = originalCagePosition + randomOffset;
}
// 3. 【演出:両手のコントローラーを定期的に微振動させる】
hapticTimer += Time.deltaTime;
if (hapticTimer >= 0.1f) // 0.1秒ごとにブルブルと脈打つような振動を送る
{
TriggerBothHandHaptics(hapticAmplitude, 0.08f);
hapticTimer = 0f;
}
yield return null;
}
// ─── ロード完了後の処理 ───
// 4. 【演出の停止】エレベーターの揺れをピタッと止め、位置を綺麗にリセットする
if (elevatorCageTransform != null)
{
elevatorCageTransform.localPosition = originalCagePosition;
}
if (progressText != null) progressText.text = "ARRIVED";
if (progressSlider != null) progressSlider.value = 1f;
// 到着後の余韻ガタガタが止まってから、扉が開いてシーンが変わるまでの静寂1秒
yield return new WaitForSeconds(1.0f);
Debug.Log("🎉 ボスステージに到着。シーンを切り替えます。");
asyncLoad.allowSceneActivation = true;
}
/// <summary>
/// 左右両方のコントローラーを同時に微振動させるヘルパーメソッド
/// </summary>
private void TriggerBothHandHaptics(float amplitude, float duration)
{
// 左手
InputDevice leftDevice = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
if (leftDevice.isValid) leftDevice.SendHapticImpulse(0, amplitude, duration);
// 右手
InputDevice rightDevice = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
if (rightDevice.isValid) rightDevice.SendHapticImpulse(0, amplitude, duration);
}
}