ボスステージが壊れていた
リカバリーしてエレベーターを作った
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.XR; // 振動機能のために必要
|
||||
using UnityEngine.XR;
|
||||
using System.Collections;
|
||||
|
||||
public class ElevatorSceneTransition : MonoBehaviour
|
||||
@@ -15,32 +15,33 @@ public class ElevatorSceneTransition : MonoBehaviour
|
||||
[SerializeField] private Text progressText;
|
||||
[SerializeField] private Slider progressSlider;
|
||||
|
||||
// ─── ★ここから下降演出用の設定項目を追加 ───
|
||||
[Header("エレベーター下降演出設定")]
|
||||
[Tooltip("エレベーターの部屋(壁や床、UIすべて)をまとめている一番親のTransformを指定してください")]
|
||||
[Tooltip("エレベーターの部屋(壁や床、UIすべて)をまとめているオブジェクトを指定してください(※プレイヤーは外しておきます)")]
|
||||
[SerializeField] private Transform elevatorCageTransform;
|
||||
|
||||
[Tooltip("ガタガタ揺れる激しさ(ミリ単位。0.01~0.03あたりがVR酔いしにくく自然です)")]
|
||||
[Tooltip("ガタガタ揺れる激しさ(0.01~0.03あたりが自然です)")]
|
||||
[SerializeField] private float shakeMagnitude = 0.015f;
|
||||
|
||||
[Tooltip("下降中のコントローラーの振動の強さ(0.0 ~ 1.0)")]
|
||||
[SerializeField] private float hapticAmplitude = 0.15f;
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
// ─── ★新設:親子関係にしないためのプレイヤー登録枠 ───
|
||||
[Header("プレイヤーの同期設定")]
|
||||
[Tooltip("XR Origin(またはXR Rig)のTransformを直接ドラッグ&ドロップしてください")]
|
||||
[SerializeField] private Transform playerTransform;
|
||||
// ─────────────────────────────────────────────────────
|
||||
|
||||
private bool isLoadingStarted = false;
|
||||
private Vector3 originalCagePosition; // 揺らす前のエレベーターの初期位置を記憶する用
|
||||
private Vector3 originalCagePosition;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (loadingCanvas != null)
|
||||
{
|
||||
loadingCanvas.SetActive(false);
|
||||
}
|
||||
if (loadingCanvas != null) loadingCanvas.SetActive(false);
|
||||
|
||||
// 部屋の初期位置を保存
|
||||
if (elevatorCageTransform != null)
|
||||
{
|
||||
originalCagePosition = elevatorCageTransform.localPosition;
|
||||
// ワールド空間での初期位置を記憶(localPositionからpositionに変更し、より確実に)
|
||||
originalCagePosition = elevatorCageTransform.position;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +52,14 @@ public class ElevatorSceneTransition : MonoBehaviour
|
||||
if (other.CompareTag(playerTag))
|
||||
{
|
||||
isLoadingStarted = true;
|
||||
Debug.Log("🛗 プレイヤー乗車:下降演出と非同期ロードを開始します。");
|
||||
|
||||
// ★安全対策:接触したプレイヤーのTransformを自動でキャッシュする
|
||||
if (playerTransform == null)
|
||||
{
|
||||
playerTransform = other.transform;
|
||||
}
|
||||
|
||||
Debug.Log("🛗 プレイヤー乗車:親子関係なしのデルタ同期で下降演出を開始します。");
|
||||
StartCoroutine(LoadSceneAsyncRoutine());
|
||||
}
|
||||
}
|
||||
@@ -60,34 +68,42 @@ public class ElevatorSceneTransition : MonoBehaviour
|
||||
{
|
||||
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. 【演出:部屋をガタガタ揺らす】
|
||||
// 初期位置をベースに、毎フレームごくわずかなランダム座標を計算して部屋を揺らす
|
||||
// ─── ★【超重要】親子関係なしでプレイヤーを完全同期させるロジック ───
|
||||
|
||||
// 1. 動かす前の、このフレームにおけるエレベーターの現在位置を記録
|
||||
Vector3 previousCagePosition = elevatorCageTransform.position;
|
||||
|
||||
// 2. エレベーターの部屋だけをランダムにガタガタ動かす
|
||||
if (elevatorCageTransform != null)
|
||||
{
|
||||
Vector3 randomOffset = Random.insideUnitSphere * shakeMagnitude;
|
||||
// ※左右前後のブレ(X, Z)のみを揺らし、Y(上下)はあえて固定すると「ガタガタ感」が出ます
|
||||
randomOffset.y = 0;
|
||||
elevatorCageTransform.localPosition = originalCagePosition + randomOffset;
|
||||
randomOffset.y = 0; // 横揺れのみ
|
||||
elevatorCageTransform.position = originalCagePosition + randomOffset;
|
||||
}
|
||||
|
||||
// 3. 【演出:両手のコントローラーを定期的に微振動させる】
|
||||
// 3. 「この1フレームでエレベーターが実際に動いた移動差分(デルタ)」を計算
|
||||
Vector3 cageDelta = elevatorCageTransform.position - previousCagePosition;
|
||||
|
||||
// 4. その移動差分を、プレイヤーの座標にもそのまま上乗せして足し算する
|
||||
if (playerTransform != null && cageDelta != Vector3.zero)
|
||||
{
|
||||
playerTransform.position += cageDelta;
|
||||
}
|
||||
// ───────────────────────────────────────────────────────────────────
|
||||
|
||||
hapticTimer += Time.deltaTime;
|
||||
if (hapticTimer >= 0.1f) // 0.1秒ごとにブルブルと脈打つような振動を送る
|
||||
if (hapticTimer >= 0.1f)
|
||||
{
|
||||
TriggerBothHandHaptics(hapticAmplitude, 0.08f);
|
||||
hapticTimer = 0f;
|
||||
@@ -96,34 +112,30 @@ public class ElevatorSceneTransition : MonoBehaviour
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// ─── ロード完了後の処理 ───
|
||||
|
||||
// 4. 【演出の停止】エレベーターの揺れをピタッと止め、位置を綺麗にリセットする
|
||||
// 到着後、エレベーターの位置を元の位置に綺麗に戻す
|
||||
if (elevatorCageTransform != null)
|
||||
{
|
||||
elevatorCageTransform.localPosition = originalCagePosition;
|
||||
// 最後の移動差分を計算してプレイヤーを戻す
|
||||
Vector3 previousCagePosition = elevatorCageTransform.position;
|
||||
elevatorCageTransform.position = originalCagePosition;
|
||||
Vector3 cageDelta = elevatorCageTransform.position - previousCagePosition;
|
||||
if (playerTransform != null) playerTransform.position += cageDelta;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
122
Assets/Scripts/VRDoorController.cs
Normal file
122
Assets/Scripts/VRDoorController.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// 1つのトリガーで左右のドアを反対方向にスライド開閉させ、
|
||||
/// 一定時間後に自動で閉じるクラス
|
||||
/// </summary>
|
||||
public class VRDoorController : MonoBehaviour
|
||||
{
|
||||
[Header("ドアのオブジェクト登録")]
|
||||
[Tooltip("左側にスライドさせたいドアのTransformを指定してください")]
|
||||
[SerializeField] private Transform leftDoor;
|
||||
[Tooltip("右側にスライドさせたいドアのTransformを指定してください")]
|
||||
[SerializeField] private Transform rightDoor;
|
||||
|
||||
[Header("スライド量と速度の設定")]
|
||||
[Tooltip("ドアが横に何メートルずれるか(移動量)")]
|
||||
[SerializeField] private float slideDistance = 1.0f;
|
||||
[Tooltip("ドアが完全に開ききる(閉じきる)までにかかる時間(秒)")]
|
||||
[SerializeField] private float openSpeed = 1.2f;
|
||||
[Tooltip("ドアが開ききった後、自動で閉まり始めるまでの待ち時間(秒)")]
|
||||
[SerializeField] private float autoCloseDelay = 4.0f;
|
||||
|
||||
// ドアの「閉じた位置」と「開いた位置」の座標を記憶する変数
|
||||
private Vector3 leftDoorClosedPos;
|
||||
private Vector3 rightDoorClosedPos;
|
||||
private Vector3 leftDoorOpenPos;
|
||||
private Vector3 rightDoorOpenPos;
|
||||
|
||||
// ドアの状態を管理するフラグ(バグ連打の防止用)
|
||||
private bool isOpen = false;
|
||||
private bool isMoving = false;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// 1. ゲーム開始時の位置を「閉じた状態」として記憶
|
||||
if (leftDoor != null)
|
||||
{
|
||||
leftDoorClosedPos = leftDoor.localPosition;
|
||||
// 左ドアはローカルのX軸のマイナス方向へスライドさせる
|
||||
leftDoorOpenPos = leftDoorClosedPos + new Vector3(-slideDistance, 0, 0);
|
||||
}
|
||||
|
||||
if (rightDoor != null)
|
||||
{
|
||||
rightDoorClosedPos = rightDoor.localPosition;
|
||||
// 右ドアはローカルのX軸のプラス方向へスライドさせる
|
||||
rightDoorOpenPos = rightDoorClosedPos + new Vector3(slideDistance, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 【外部連携用】VRのボタンが押されたときに呼び出す公開メソッド
|
||||
/// </summary>
|
||||
public void OnButtonPress()
|
||||
{
|
||||
// すでに移動中、またはすでに開いている場合はボタンの入力を完全に無視する
|
||||
if (isMoving || isOpen) return;
|
||||
|
||||
// 開いてから自動で閉まるまでの一連のコルーチンを始動
|
||||
StartCoroutine(OpenAndAutoCloseRoutine());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ドアを開け、待機し、自動で閉める一連の流れを管理するコルーチン
|
||||
/// </summary>
|
||||
private IEnumerator OpenAndAutoCloseRoutine()
|
||||
{
|
||||
// ─── 1. ドアを開ける処理 ───
|
||||
isMoving = true;
|
||||
float elapsedTime = 0f;
|
||||
|
||||
while (elapsedTime < openSpeed)
|
||||
{
|
||||
elapsedTime += Time.deltaTime;
|
||||
float t = elapsedTime / openSpeed;
|
||||
|
||||
// ★VR酔い・チープさ対策:数値を滑らかに補間して、リアルな加減速(イージング)をかける
|
||||
float easedT = Mathf.SmoothStep(0f, 1f, t);
|
||||
|
||||
if (leftDoor != null) leftDoor.localPosition = Vector3.Lerp(leftDoorClosedPos, leftDoorOpenPos, easedT);
|
||||
if (rightDoor != null) rightDoor.localPosition = Vector3.Lerp(rightDoorClosedPos, rightDoorOpenPos, easedT);
|
||||
|
||||
yield return null; // 1フレーム待機
|
||||
}
|
||||
|
||||
// 完全に開ききった座標で固定
|
||||
if (leftDoor != null) leftDoor.localPosition = leftDoorOpenPos;
|
||||
if (rightDoor != null) rightDoor.localPosition = rightDoorOpenPos;
|
||||
|
||||
isOpen = true;
|
||||
isMoving = false;
|
||||
Debug.Log("🚪 ドアが完全に開きました。");
|
||||
|
||||
// ─── 2. 開いた状態での待機(自動クローズのカウントダウン) ───
|
||||
yield return new WaitForSeconds(autoCloseDelay);
|
||||
|
||||
// ─── 3. ドアを閉じる処理 ───
|
||||
isMoving = true;
|
||||
isOpen = false;
|
||||
elapsedTime = 0f;
|
||||
|
||||
while (elapsedTime < openSpeed)
|
||||
{
|
||||
elapsedTime += Time.deltaTime;
|
||||
float t = elapsedTime / openSpeed;
|
||||
float easedT = Mathf.SmoothStep(0f, 1f, t);
|
||||
|
||||
if (leftDoor != null) leftDoor.localPosition = Vector3.Lerp(leftDoorOpenPos, leftDoorClosedPos, easedT);
|
||||
if (rightDoor != null) rightDoor.localPosition = Vector3.Lerp(rightDoorOpenPos, rightDoorClosedPos, easedT);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// 完全に閉じた座標で固定
|
||||
if (leftDoor != null) leftDoor.localPosition = leftDoorClosedPos;
|
||||
if (rightDoor != null) rightDoor.localPosition = rightDoorClosedPos;
|
||||
|
||||
isMoving = false;
|
||||
Debug.Log("🔒 ドアが自動で閉じました。");
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/VRDoorController.cs.meta
Normal file
2
Assets/Scripts/VRDoorController.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c3e120316425604197ba905dffcef0d
|
||||
Reference in New Issue
Block a user