From c13225f5e33190a92bbcd15b3c5830bb0c6b53cb Mon Sep 17 00:00:00 2001 From: oogushiyuuga Date: Tue, 30 Jun 2026 10:02:08 +0900 Subject: [PATCH] =?UTF-8?q?Revert=20"=E3=82=B9=E3=82=AF=E3=83=AA=E3=83=97?= =?UTF-8?q?=E3=83=88=E3=81=AE=E6=95=B4=E7=90=86"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e8bdb0920dacb0fcc492e653b95a2f4d26b2345a. --- Assets/Scenes/BossStage.unity | 4 +- Assets/Scripts/CodingModeGridManager.cs | 46 ++++++++++----- Assets/Scripts/EnemyAI.cs | 76 +++++++++++++++---------- Assets/Scripts/PlayerStatusManager.cs | 35 +++++++----- Assets/Scripts/VRPunchAttack.cs | 23 +++++--- Assets/Scripts/VRUIDoorFaceFollow.cs | 13 +++-- 6 files changed, 123 insertions(+), 74 deletions(-) diff --git a/Assets/Scenes/BossStage.unity b/Assets/Scenes/BossStage.unity index e5465f2..06b2e3e 100644 --- a/Assets/Scenes/BossStage.unity +++ b/Assets/Scenes/BossStage.unity @@ -193,8 +193,6 @@ Transform: m_CorrespondingSourceObject: {fileID: 400000, guid: d9d1fbfcf69364ffd8f9c6ade9ce90fe, type: 3} m_PrefabInstance: {fileID: 13762580} m_PrefabAsset: {fileID: 0} -<<<<<<< HEAD -======= --- !u!1001 &48320566 PrefabInstance: m_ObjectHideFlags: 0 @@ -256,7 +254,6 @@ PrefabInstance: m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 483f930f7cf5dca46a4974b3a5f3231a, type: 3} ->>>>>>> 4d1dc01b620a200265bcb2d187a5e148601b69d5 --- !u!1001 &64373871 PrefabInstance: m_ObjectHideFlags: 0 @@ -6834,3 +6831,4 @@ SceneRoots: - {fileID: 581708908} - {fileID: 73494051} - {fileID: 1033763925} + - {fileID: 48320566} diff --git a/Assets/Scripts/CodingModeGridManager.cs b/Assets/Scripts/CodingModeGridManager.cs index f65cd44..f1eedff 100644 --- a/Assets/Scripts/CodingModeGridManager.cs +++ b/Assets/Scripts/CodingModeGridManager.cs @@ -5,10 +5,16 @@ using System.Collections.Generic; public class CodingModeGridManager : MonoBehaviour { + [Header("スティック入力設定")] + [Tooltip("移動に使用するコントローラーのスティックのInputActionPropertyを指定してください")] [SerializeField] private InputActionProperty thumbstickAction; - [SerializeField] private float inputThreshold = 0.5f; // スティックをどれくらい倒したら動くか + [Range(0.1f, 0.9f)] [SerializeField] private float inputThreshold = 0.5f; // スティックをどれくらい倒したら動くか + + [Header("5x5 マス目(UI Image)の登録")] + [Tooltip("ヒエラルキー上の25個のマス目のImageコンポーネントを、左上(0)から右下(24)の順番で格納してください")] [SerializeField] private List gridCells = new List(); + [Header("マスの配色設定")] [SerializeField] private Color colorNormal = Color.gray; [SerializeField] private Color colorPlayer = Color.green; // 自機(プレイヤー) [SerializeField] private Color colorGoal = Color.yellow; // ゴール @@ -46,6 +52,7 @@ public class CodingModeGridManager : MonoBehaviour private void Update() { + // ─── ★Time.timeScale = 0 でも動くスティック入力移動ロジック ─── if (thumbstickAction.action == null) return; Vector2 stickInput = thumbstickAction.action.ReadValue(); @@ -62,36 +69,40 @@ public class CodingModeGridManager : MonoBehaviour { if (Mathf.Abs(stickInput.x) > Mathf.Abs(stickInput.y)) { - if (stickInput.x > inputThreshold) MovePlayer(1, 0); - else if (stickInput.x < -inputThreshold) MovePlayer(-1, 0); + // 横移動 + if (stickInput.x > inputThreshold) MovePlayer(1, 0); // 右 + else if (stickInput.x < -inputThreshold) MovePlayer(-1, 0); // 左 } else { - if (stickInput.y > inputThreshold) MovePlayer(0, -1); - else if (stickInput.y < -inputThreshold) MovePlayer(0, 1); + // 縦移動 (UIの配列構造上、上に行くとYマイナス、下に行くとYプラスとなるよう計算) + if (stickInput.y > inputThreshold) MovePlayer(0, -1); // 上 + else if (stickInput.y < -inputThreshold) MovePlayer(0, 1); // 下 } } } - /// 盤面を初期化し、ランダムに再配置する(PlayerStatusManagerから呼ばれる) + /// + /// 盤面を完全に初期化し、失敗ゾーンやチェックポイントをランダムに再配置する(PlayerStatusManagerから呼ばれる) + /// public void ResetAndGenerateMinigame() { accumulatedBuffs.Clear(); - // 全マスを通常マスとして初期化 + // 1. 全マスを通常マスとして初期化 for (int i = 0; i < 25; i++) { cellLogicArray[i] = CellType.Normal; checkpointBuffTypeArray[i] = ""; } - // スタートとゴールの固定配置、(余裕があればランダムに) + // 2. スタートとゴールの固定配置 (左上スタート、右下ゴール) playerX = 0; playerY = 0; goalX = 4; goalY = 4; cellLogicArray[GetIndex(0, 0)] = CellType.Start; cellLogicArray[GetIndex(4, 4)] = CellType.Goal; - // 失敗ゾーンをランダムに5個配置 + // 3. 失敗ゾーン(赤マス)をランダムに5個配置 (スタート・ゴールには被らせない) int failZonesPlaced = 0; while (failZonesPlaced < 5) { @@ -103,7 +114,7 @@ public class CodingModeGridManager : MonoBehaviour } } - // チェックポイントを3つのバフに対応させてランダムに3個配置 + // 4. チェックポイント(青マス)を3つのバフに対応させてランダムに3個配置 string[] buffPool = { "AttackUp", "DefenseUp", "Heal" }; int checkpointsPlaced = 0; while (checkpointsPlaced < 3) @@ -117,10 +128,13 @@ public class CodingModeGridManager : MonoBehaviour } } + // 5. 視覚的(UIの色)に反映 RedrawGridGraphic(); } + /// /// プレイヤーの位置を指定された方向へ動かし、移動先のイベントを判定する + /// private void MovePlayer(int xDirection, int yDirection) { int nextX = Mathf.Clamp(playerX + xDirection, 0, 4); @@ -136,7 +150,7 @@ public class CodingModeGridManager : MonoBehaviour int currentIndex = GetIndex(playerX, playerY); CellType landedCell = cellLogicArray[currentIndex]; - Debug.Log("({playerX}, {playerY}) | マス属性: {landedCell}"); + Debug.Log($"👾 カーソル移動: ({playerX}, {playerY}) | マス属性: {landedCell}"); // 移動先のマスに応じた処理 switch (landedCell) @@ -150,7 +164,7 @@ public class CodingModeGridManager : MonoBehaviour if (!accumulatedBuffs.Contains(buff)) { accumulatedBuffs.Add(buff); - Debug.Log("バフコード抽出成功: [{buff}] を一時キープ中!"); + Debug.Log($"💚 バフコード抽出成功: [{buff}] を一時キープ中!"); } break; @@ -158,10 +172,14 @@ public class CodingModeGridManager : MonoBehaviour PlayerStatusManager.Instance.CompleteCodingMode(accumulatedBuffs); // クリア!バフ適用 return; } + + // 画面の色を最新状態に更新 RedrawGridGraphic(); } + /// /// 現在のロジック配列に基づいて、25個のUI Imageの色をまとめて上書き変更する + /// private void RedrawGridGraphic() { for (int y = 0; y < 5; y++) @@ -181,7 +199,7 @@ public class CodingModeGridManager : MonoBehaviour case CellType.Goal: gridCells[index].color = colorGoal; break; } - // チェックポイントをすでに踏み抜いている場合は、獲得済みとして通常色に戻す演出 + // チェックポイントをすでに踏み抜いている場合は、獲得済みとして通常色に戻す演出(任意) if (cellLogicArray[index] == CellType.Checkpoint && accumulatedBuffs.Contains(checkpointBuffTypeArray[index])) { gridCells[index].color = colorNormal * 0.7f; // 少し暗いグレーにして区別 @@ -189,7 +207,7 @@ public class CodingModeGridManager : MonoBehaviour } } - // 最後にプレイヤーのいるマスを自機の色で最優先に塗り替える + // 最後にプレイヤーのいるマスを「自機の色」で最優先に塗り替える int playerIndex = GetIndex(playerX, playerY); if (gridCells[playerIndex] != null) { diff --git a/Assets/Scripts/EnemyAI.cs b/Assets/Scripts/EnemyAI.cs index d2ca9f3..8cbcf7e 100644 --- a/Assets/Scripts/EnemyAI.cs +++ b/Assets/Scripts/EnemyAI.cs @@ -16,23 +16,30 @@ public class EnemyAI : MonoBehaviour Stun // 怯み } - // 現在の状態 + [Header("現在の状態")] [SerializeField] private AIState currentState = AIState.Wander; - - // 索敵設定 + + [Header("索敵設定")] [SerializeField] private float detectionRange = 10f; [SerializeField] private float loseRange = 15f; [SerializeField] private string playerTag = "Player"; - // 攻撃設定 + [Header("攻撃設定")] + [Tooltip("この距離に近づいたら攻撃 (メートル)")] [SerializeField] private float attackRange = 1.5f; + [Tooltip("パンチの攻撃力")] [SerializeField] private float attackDamage = 10f; + [Tooltip("一度攻撃が終了してから、次の攻撃を開始するまでの待ち時間 (秒)")] [SerializeField] private float attackCooldown = 2.0f; - [SerializeField] private float telegraphDuration = 0.6f; //攻撃ため時間 + [Tooltip("攻撃の予兆時間 (秒)")] + [SerializeField] private float telegraphDuration = 0.6f; [SerializeField] private Collider rightHandCollider; - [SerializeField] private float comboInterval = 0.2f; // 連続攻撃のインターバル - // 索敵設定 + [Header("ループ攻撃の調整")] + [Tooltip("連続攻撃の間に挟む最低限のインターバル (秒)")] + [SerializeField] private float comboInterval = 0.2f; + + [Header("徘徊(Wander)設定")] [SerializeField] private float wanderRadius = 8f; [SerializeField] private float minWaitTime = 2f; [SerializeField] private float maxWaitTime = 4f; @@ -70,7 +77,7 @@ public class EnemyAI : MonoBehaviour UpdateRotationOnAttack(); } - // AI メインループ (思考ロジック) + #region AI メインループ (思考ロジック) private IEnumerator AILoop() { while (true) @@ -113,8 +120,10 @@ public class EnemyAI : MonoBehaviour playerTransform = playerObj.transform; } } + #endregion - // 徘徊状態の思考ロジック + #region 各ステートの固有行動 + /// 【徘徊状態】の思考ロジック private void WanderBehavior() { if (playerTransform != null) @@ -126,7 +135,7 @@ public class EnemyAI : MonoBehaviour currentState = AIState.Chase; isWandering = false; agent.ResetPath(); - Debug.Log($"{gameObject.name}: プレイヤーを発見、追跡します。"); + Debug.Log($"👁️ {gameObject.name}: プレイヤーを発見! 追跡します。"); return; } } @@ -138,7 +147,7 @@ public class EnemyAI : MonoBehaviour } } - // 追跡状態の思考ロジック + /// 【追跡状態】の思考ロジック private void ChaseBehavior() { if (playerTransform == null) @@ -162,7 +171,7 @@ public class EnemyAI : MonoBehaviour { currentState = AIState.Wander; agent.ResetPath(); - Debug.Log($"{gameObject.name}: プレイヤーを見失った。"); + Debug.Log($"❓ {gameObject.name}: プレイヤーを見失った。"); return; } @@ -173,7 +182,7 @@ public class EnemyAI : MonoBehaviour } } - // 攻撃状態の思考ロジック + /// 【攻撃状態】の思考ロジック private void AttackBehavior() { if (playerTransform == null) @@ -191,14 +200,16 @@ public class EnemyAI : MonoBehaviour return; } - // クールダウン中でなければ攻撃コルーチンを実行(クールダウン中の場合は、Update内の処理によりプレイヤーの方向を向きながら待機) + // クールダウン中でなければ攻撃コルーチンを実行(クールダウン中の場合は、Update内の処理によりプレイヤーの方向を向きながら待機します) if (!isCooldown) { StartCoroutine(PerformPunchAttack()); } } + #endregion - // エージェントの移動状態に応じてAnimatorのSpeedパラメータを更新する + #region アニメーション・回転の制御メソッド + /// エージェントの移動状態に応じてAnimatorのSpeedパラメータを更新する private void UpdateAnimation() { float targetSpeed = 0f; @@ -213,7 +224,7 @@ public class EnemyAI : MonoBehaviour anim.SetFloat("Speed", targetSpeed, 0.1f, Time.deltaTime); } - // 攻撃ステートの際、プレイヤーの方向へ滑らかに旋回させる + /// 攻撃ステートの際、プレイヤーの方向へ滑らかに旋回させる private void UpdateRotationOnAttack() { if (currentState == AIState.Attack && playerTransform != null && !isKnockbacking && currentState != AIState.Stun) @@ -228,6 +239,7 @@ public class EnemyAI : MonoBehaviour } } } + #endregion // ダメージを受けた際に、EnemyhHealthから呼び出されるのけぞり開始メソッド public void TriggerKnockback(float duration) @@ -325,7 +337,8 @@ public class EnemyAI : MonoBehaviour StartCoroutine(AILoop()); } - // 徘徊時のランダム移動を制御するコルーチン + #region 攻撃・移動のコルーチン処理 + /// 徘徊時のランダム移動を制御するコルーチン private IEnumerator WanderMoveRoutine() { isWandering = true; @@ -375,14 +388,14 @@ public class EnemyAI : MonoBehaviour isWandering = false; } - // 予兆から攻撃アニメーションのトリガーまでを制御するコルーチン + /// 予兆から攻撃アニメーションのトリガーまでを制御するコルーチン private IEnumerator PerformPunchAttack() { isAttacking = true; - isCooldown = true; // ここで攻撃フラグをロック + isCooldown = true; // ここで攻撃フラグをロックします anim.SetTrigger("Telegraph"); - Debug.Log($"{gameObject.name}: 攻撃の溜め開始"); + Debug.Log($"⚠️ {gameObject.name}: 攻撃の予兆(溜め)開始"); yield return new WaitForSeconds(telegraphDuration); @@ -391,23 +404,25 @@ public class EnemyAI : MonoBehaviour anim.SetTrigger("Attack"); } - // 連続攻撃成功時の、クイックなクールダウン解除処理 + /// 連続攻撃成功時の、クイックなクールダウン解除処理 private IEnumerator ResetCooldownQuickly() { yield return new WaitForSeconds(comboInterval); isCooldown = false; } - // コンボが途切れた際の、通常の攻撃クールダウン解除処理 + /// コンボが途切れた際の、通常の攻撃クールダウン解除処理 private IEnumerator ResetCooldown() { // 指定された秒数待機する yield return new WaitForSeconds(attackCooldown); isCooldown = false; - Debug.Log($"{gameObject.name}: 攻撃クールダウンが終了しました。再攻撃可能です。"); + Debug.Log($"✅ {gameObject.name}: 攻撃クールダウンが終了しました。再攻撃可能です。"); } + #endregion - // 攻撃アニメーションのヒットフレームで実行されるヒット判定(Animation Eventから呼び出し) + #region アニメーションイベント(外部からのコールバック) + /// 攻撃アニメーションのヒットフレームで実行されるヒット判定(Animation Eventから呼び出し) public void OnPunchHit() { if (isKnockbacking || currentState == AIState.Stun) return; @@ -415,7 +430,7 @@ public class EnemyAI : MonoBehaviour SetFistCollider(true); } - // Recovery(硬直)アニメーションの終了時に実行される処理(Animation Eventから呼び出し) + /// Recovery(硬直)アニメーションの終了時に実行される処理(Animation Eventから呼び出し) public void OnRecoveryEnd() { if(isKnockbacking || currentState == AIState.Stun) return; @@ -436,7 +451,7 @@ public class EnemyAI : MonoBehaviour if (distanceToPlayer <= attackRange) { StartCoroutine(ResetCooldownQuickly()); - Debug.Log($"{gameObject.name}: プレイヤーがまだ射程内です。連続攻撃を実行します。"); + Debug.Log($"🔄 {gameObject.name}: プレイヤーがまだ射程内です。連続攻撃(コンボ)を実行します。"); } else { @@ -446,8 +461,10 @@ public class EnemyAI : MonoBehaviour Debug.Log($"🏃 {gameObject.name}: プレイヤーが離れたため追跡に戻ります。({attackCooldown}秒の攻撃クールダウンを適用)"); } } + #endregion - // 指定された中心座標の範囲内から、NavMesh上の有効なランダム座標を取得する + #region ヘルパー・デバッグ用メソッド + /// 指定された中心座標の範囲内から、NavMesh上の有効なランダム座標を取得する private void SetFistCollider(bool enabledState) { @@ -468,8 +485,8 @@ public class EnemyAI : MonoBehaviour } return center; } - - // エディタのSceneビューに索敵・攻撃範囲をギズモとして描画する + + /// エディタのSceneビューに索敵・攻撃範囲をギズモとして描画する private void OnDrawGizmosSelected() { // 索敵範囲(赤) @@ -484,4 +501,5 @@ public class EnemyAI : MonoBehaviour Gizmos.color = Color.blue; Gizmos.DrawWireSphere(transform.position, attackRange); } + #endregion } \ No newline at end of file diff --git a/Assets/Scripts/PlayerStatusManager.cs b/Assets/Scripts/PlayerStatusManager.cs index bbae23e..6402f72 100644 --- a/Assets/Scripts/PlayerStatusManager.cs +++ b/Assets/Scripts/PlayerStatusManager.cs @@ -6,18 +6,19 @@ public class PlayerStatusManager : MonoBehaviour { public static PlayerStatusManager Instance { get; private set; } - // CodingModeスタート入力ボタン + [Header("Codingモード用 入力設定")] [SerializeField] private InputActionProperty zlButtonAction; [SerializeField] private InputActionProperty zrButtonAction; - // ゲージ設定 + [Header("ゲージ設定")] [SerializeField] private float maxGauge = 100f; [SerializeField] private float currentGauge = 0f; - // 表示UI設定 + [Header("表示UI設定")] + [Tooltip("ミニゲーム画面をまとめている親オブジェクトを指定してください")] [SerializeField] private GameObject codingModeUI; - // バフパラメータ設定 + [Header("バフパラメータ設定")] [SerializeField] private float buffDuration = 10f; [SerializeField] private float attackBuffMultiplier = 1.5f; [SerializeField] private float defenseBuffMultiplier = 0.5f; @@ -70,7 +71,7 @@ public class PlayerStatusManager : MonoBehaviour if (isCodingMode) return; currentGauge += amount; currentGauge = Mathf.Clamp(currentGauge, 0f, maxGauge); - Debug.Log($"共通ゲージ増加: {currentGauge} / {maxGauge}"); + Debug.Log($"🔋 共通ゲージ増加: {currentGauge} / {maxGauge}"); } private void CheckComboInput() @@ -98,15 +99,18 @@ public class PlayerStatusManager : MonoBehaviour if (codingModeUI != null) { codingModeUI.SetActive(true); + // ★新設:画面が開いた瞬間にミニゲームの盤面をランダム生成してリセットする CodingModeGridManager gridManager = codingModeUI.GetComponentInChildren(); if (gridManager != null) gridManager.ResetAndGenerateMinigame(); } } - // ミニゲームクリア時:獲得したバフリストをすべて適用して現実世界を再開する + /// + /// ★ミニゲームクリア時:獲得したバフリストをすべて適用して現実世界を再開する + /// public void CompleteCodingMode(List earnedBuffs) { - Debug.Log("ハッキング成功! ミニゲームクリア!現実世界に復帰します。"); + Debug.Log("💻 【ハッキング成功】 ミニゲームクリア!現実世界に復帰します。"); foreach (string buff in earnedBuffs) { @@ -116,10 +120,12 @@ public class PlayerStatusManager : MonoBehaviour ResumeGameplay(); } - // ミニゲーム失敗時:失敗ゾーン接触による強制終了処理(バフなしで復帰) + /// + /// ★ミニゲーム失敗時:失敗ゾーン接触による強制終了処理(バフなしで復帰) + /// public void FailCodingMode() { - Debug.Log("ハッキング強制失敗 失敗ゾーンに接触しました。バフなしで復帰します。"); + Debug.Log("🚨 【ハッキング強制失敗】 失敗ゾーンに接触しました。バフなしで復帰します。"); ResumeGameplay(); } @@ -138,14 +144,15 @@ public class PlayerStatusManager : MonoBehaviour { case "AttackUp": attackBuffTimer = buffDuration; - Debug.Log($"攻撃力UPが適用されました。効果時間: {buffDuration}秒"); + Debug.Log($"⚔️ 攻撃力UPが適用されました。効果時間: {buffDuration}秒"); break; case "DefenseUp": defenseBuffTimer = buffDuration; - Debug.Log($"防御力UPが適用されました。効果時間: {buffDuration}秒"); + Debug.Log($"🛡️ 防御力UPが適用されました。効果時間: {buffDuration}秒"); break; case "Heal": - Debug.Log($"HP回復が適用されました。回復量: {hpHealAmount}"); + Debug.Log($"💚 HP回復が適用されました。回復量: {hpHealAmount}"); + // ※将来の拡張:PlayerHealth.Instance.Heal(hpHealAmount); break; } } @@ -155,13 +162,13 @@ public class PlayerStatusManager : MonoBehaviour if (attackBuffTimer > 0f) { attackBuffTimer -= Time.deltaTime; - if (attackBuffTimer <= 0f) Debug.Log("攻撃力UPバフの効果が終了しました。"); + if (attackBuffTimer <= 0f) Debug.Log("⚔️ 攻撃力UPバフの効果が終了しました。"); } if (defenseBuffTimer > 0f) { defenseBuffTimer -= Time.deltaTime; - if (defenseBuffTimer <= 0f) Debug.Log("防御力UPバフの効果が終了しました。"); + if (defenseBuffTimer <= 0f) Debug.Log("🛡️ 防御力UPバフの効果が終了しました。"); } } } \ No newline at end of file diff --git a/Assets/Scripts/VRPunchAttack.cs b/Assets/Scripts/VRPunchAttack.cs index ecc65be..ea21799 100644 --- a/Assets/Scripts/VRPunchAttack.cs +++ b/Assets/Scripts/VRPunchAttack.cs @@ -10,17 +10,18 @@ public class VRInputPunch : MonoBehaviour [SerializeField] private XRNode controllerNode = XRNode.RightHand; [SerializeField] private VRInputPoseDetector poseDetector; - // 攻撃設定 + [Header("攻撃(パンチ)設定")] [SerializeField] private float minPunchSpeed = 2.0f; // パンチとして判定する最低速度 (m/s) [SerializeField] private float damageMultiplier = 10.0f; // ダメージ倍率 [SerializeField] private float hapticAmplitude = 0.5f; // 通常ヒットの振動の強さ [SerializeField] private float hapticDuration = 0.1f; // 通常ヒットの振動の長さ - // パリィ設定 + [Header("パリィ設定")] [SerializeField] private float minParrySpeed = 1.0f; // パリィできるパンチとして判定する最低速度 (m/s) [SerializeField] private float parryStunDuration = 3.0f; // スタン時間(秒) [SerializeField] private float parryHapticAmplitude = 0.9f; // パリィ成功時の振動の強さ [SerializeField] private float parryHapticDuration = 0.25f; // パリィ成功時の振動の長さ + // ───────────────────────────────────────── private void OnEnable() { @@ -52,29 +53,35 @@ public class VRInputPunch : MonoBehaviour Vector3 velocity = velocityAction.action.ReadValue(); float speed = velocity.magnitude; - // パリィ判定 + //【パリィ判定】当たったオブジェクトが敵の拳だった場合 if (other.CompareTag("EnemyFist")) { - Debug.Log($"[パリィチェック] 敵の拳と接触。プレイヤーの手の速度: {speed:F2} m/s / 構え状態: {poseDetector.IsPosing}"); + Debug.Log($"🛡️ [パリィチェック] 敵の拳と接触。プレイヤーの手の速度: {speed:F2} m/s / 構え状態: {poseDetector.IsPosing}"); + // 条件:構え状態(IsPosing)である、もしくは、弾くための速度が一定以上出ている場合 if (poseDetector.IsPosing || speed >= minParrySpeed) { + // 敵の親オブジェクトからEnemyAIスクリプトを検索 EnemyAI enemyAI = other.GetComponentInParent(); if (enemyAI != null) { + // 敵の攻撃コンボを強制中断し、スタン状態にする enemyAI.TriggerParryStun(parryStunDuration); + + // パリィ成功用の強力な振動をプレイヤーに返す TriggerHaptics(parryHapticAmplitude, parryHapticDuration); - Debug.Log($"ジャストパリィ成功! 敵の体勢を崩しました。スタン時間: {parryStunDuration}秒"); - return; + Debug.Log($"🛡️ 【ジャストパリィ成功!】 敵の体勢を崩しました。スタン時間: {parryStunDuration}秒"); + return; // パリィが成立した場合は以降のパンチ処理は行わない } } else { - Debug.Log("ガード(または速度不足):敵の攻撃は防いだが、弾き返せなかった。"); + Debug.Log("🧱 ガード(または速度不足):敵の攻撃は防いだが、弾き返せなかった。"); return; } } + // ──────────────────────────────────────────────────────────────────────── // パンチ攻撃の処理 @@ -124,7 +131,7 @@ public class VRInputPunch : MonoBehaviour } } - // 引数に応じて指定された強さと長さでコントローラーを振動させる + /// 引数に応じて指定された強さと長さでコントローラーを振動させる private void TriggerHaptics(float amplitude, float duration) { UnityEngine.XR.InputDevice device = InputDevices.GetDeviceAtXRNode(controllerNode); diff --git a/Assets/Scripts/VRUIDoorFaceFollow.cs b/Assets/Scripts/VRUIDoorFaceFollow.cs index cb52217..7f21cc0 100644 --- a/Assets/Scripts/VRUIDoorFaceFollow.cs +++ b/Assets/Scripts/VRUIDoorFaceFollow.cs @@ -1,10 +1,11 @@ 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; @@ -21,15 +22,15 @@ public class VRUIDoorFaceFollow : MonoBehaviour } } - // Time.timeScale = 0 の間でも動作させるため、カメラ移動の後に実行される LateUpdate を使用 + // 全体の時間が止まっている(Time.timeScale = 0)間でも動作させるため、カメラ移動の後に実行される LateUpdate を使用します private void LateUpdate() { if (vrCameraTransform == null) return; - // UI画面が有効化された最初のフレームの処理 + // このオブジェクト(UI画面)が有効化された「最初のフレーム」の処理 if (!wasActiveLastFrame) { - // 開いた瞬間は、プレイヤーの今の向きの完全な正面に瞬間移動させる(遅れてついてくるのを防ぐため) + // 開いた瞬間は、プレイヤーの今の向きの「完全な正面」に瞬間移動させる(遅れてついてくるのを防ぐため) SetInitialPosition(); wasActiveLastFrame = true; return; @@ -45,7 +46,7 @@ public class VRUIDoorFaceFollow : MonoBehaviour wasActiveLastFrame = false; } - // 画面が開いた瞬間に、プレイヤーの正面の正しい位置・向きに強制配置する + /// 画面が開いた瞬間に、プレイヤーの正面の正しい位置・向きに強制配置する private void SetInitialPosition() { // カメラの位置から、カメラが向いている正面方向に一定距離進んだ座標を計算 @@ -60,7 +61,7 @@ public class VRUIDoorFaceFollow : MonoBehaviour transform.Rotate(0, 180, 0); } - // プレイヤーが首を動かしたり移動したりした際、画面を滑らかについてこさせる + /// プレイヤーが首を動かしたり移動したりした際、画面を滑らかについてこさせる private void SmoothFollowPlayer() { // 目的地(目標座標)の計算