bosuheya chouseimae

This commit is contained in:
ohgushiyuga
2026-07-14 14:14:48 +09:00
parent 568ed162fb
commit 1ab733c127
9 changed files with 161 additions and 42 deletions

View File

@@ -21,7 +21,16 @@ public class BossController : MonoBehaviour, IDamageble
[SerializeField] public Transform groundAnchor;
[field: SerializeField] public float AttackRadius { get; private set; } = 10f;
[field: SerializeField] public float JumpRoarDuration { get; private set; } = 5f;
[field: SerializeField] public float CeilingAttackDuration { get; private set; } = 8.0f;
[Tooltip("★新設:糸を降らせる時間間隔(秒)。数値を小さくする(例: 0.1)ほど弾数が激増して密度が上がります")]
[field: SerializeField] public float CeilingShotInterval { get; private set; } = 0.2f;
[Tooltip("★新設:地面に赤マーク(予兆)が出てから、本物の糸が降ってくるまでのタイムラグ(秒)")]
[field: SerializeField] public float WebWarningDelay { get; private set; } = 0.8f;
[Tooltip("★新設:地面に生成された糸が消えずに残り続ける時間(秒)")]
[field: SerializeField] public float WebDuration { get; private set; } = 3.0f;
[SerializeField] private GameObject warningMarkerPrefab;
[SerializeField] private GameObject webPrefab;
@@ -38,7 +47,7 @@ public class BossController : MonoBehaviour, IDamageble
// フェーズトリガー
private bool triggered50 = false;
private bool triggered25 = false;
public bool PendingUltimate { get; set; } = false;
public bool PendingUltimate { get; set; } = false;
private void Awake()
{
@@ -102,11 +111,11 @@ public class BossController : MonoBehaviour, IDamageble
public void TakeDamage(DamageInfo damageInfo)
{
currentHp -= damageInfo.amount;
currentHp -= damageInfo.amount;
currentHp = Mathf.Clamp(currentHp, 0, maxHp);
float hpPercentage = (currentHp / maxHp) * 100f;
Debug.Log($"💥 ボスに { damageInfo.amount} ダメージ。残りHP: {hpPercentage:F1}%");
Debug.Log($"💥 ボスに {damageInfo.amount} ダメージ。残りHP: {hpPercentage:F1}%");
if (hpPercentage <= 25f && !triggered25)
{
@@ -165,8 +174,11 @@ public class BossController : MonoBehaviour, IDamageble
if (webPrefab != null)
{
GameObject web = Instantiate(webPrefab, pos, Quaternion.identity);
Destroy(web, duration);
Quaternion webRotation = Quaternion.Euler(270f, 0f, 0f);
GameObject web = Instantiate(webPrefab, pos + new Vector3(0, 0.5f, 0), webRotation);
Destroy(web, duration);
}
}
@@ -180,13 +192,34 @@ public class BossController : MonoBehaviour, IDamageble
Anim.ResetTrigger("Land");
Anim.ResetTrigger("StunStart");
}
#region デバッグ用機能
/// <summary>
/// Unityインスペクターの右上メニューから実行できるデバッグ用コマンドです
/// </summary>
[ContextMenu("🛠️ デバッグ:強制必殺技(天井ジャンプ)")]
public void DebugTriggerUltimate()
{
if (!Application.isPlaying)
{
Debug.LogWarning("⚠️ ゲームが再生中(Playモード)の時のみ実行可能です。");
return;
}
Debug.Log("🛠️ 【デバッグ操作】必殺技の予約券を発行し、強制的に天井ジャンプステートへ遷移します。");
// 必殺技の発動権をONにし、現在の行動をキャンセルして天井ジャンプへ移行
PendingUltimate = true;
ChangeState<SpiderJumpToCeilingState>();
}
#endregion
}
/// 共通データ(boss参照)を自動保持し、各子ステートの無駄なコードを極限まで削ります。
public abstract class SpiderStateBase : ISpiderState
{
protected readonly BossController boss;
protected SpiderStateBase(BossController owner)
{
boss = owner;

View File

@@ -0,0 +1,44 @@
using UnityEngine;
public class BossDebugController : MonoBehaviour
{
private BossController bossController;
private void Awake()
{
// 同一オブジェクトにあるBossControllerを自動取得
bossController = GetComponent<BossController>();
}
private void Update()
{
// ─── ★キーボードの『U(Ultimate)』キーを押したら強制発動 ───
if (Input.GetKeyDown(KeyCode.U))
{
TriggerDebugUltimate();
}
// ─── ついでにあると便利な機能:『S(Stun)』キーで即座にパリィスタン ───
if (Input.GetKeyDown(KeyCode.S))
{
TriggerDebugStun();
}
}
private void TriggerDebugUltimate()
{
if (bossController == null) return;
Debug.Log("🛠️ 【キーボードデバッグ】強制的に必殺技(天井ジャンプ)を発動します。");
bossController.PendingUltimate = true;
bossController.ChangeState<SpiderJumpToCeilingState>();
}
private void TriggerDebugStun()
{
if (bossController == null) return;
Debug.Log("🛡️ 【キーボードデバッグ】強制的にパリィスタン(チャンスタイム)を発動します。");
bossController.ChangeState<SpiderStunState>();
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d2cd755b0c100204e833df85acb412e8

View File

@@ -216,10 +216,11 @@ public class SpiderJumpToCeilingState : SpiderStateBase
}
}
// ==========================================
// ■ STATE: CEILING ATTACK (インスペクター無段階調整版)
// ==========================================
public class SpiderCeilingAttackState : SpiderStateBase
{
private float stateDuration = 7.0f;
private float shotInterval = 0.4f;
private float timer = 0f;
private float shotTimer = 0f;
@@ -227,11 +228,13 @@ public class SpiderCeilingAttackState : SpiderStateBase
public override void EnterState()
{
timer = stateDuration;
// ★リファクタリング:インスペクターで設定した必殺技の長さを適用
timer = boss.CeilingAttackDuration;
shotTimer = 0f;
boss.Anim.SetBool("IsOnCeiling", true);
boss.PendingUltimate = false;
Debug.Log("🕸️ 蜘蛛ボス:天井から無数の糸を乱射中!");
Debug.Log($"🕸️ 蜘蛛ボス:天井からの乱射開始! 持続時間: {timer}秒 / 発射間隔: {boss.CeilingShotInterval}秒");
}
public override void ExitState()
@@ -247,10 +250,13 @@ public class SpiderCeilingAttackState : SpiderStateBase
timer -= Time.deltaTime;
shotTimer -= Time.deltaTime;
// タイマーがゼロになったら発射
if (shotTimer <= 0f)
{
ExecuteRandomWebAttack();
shotTimer = shotInterval;
// ★リファクタリング:インスペクターで設定した間隔(秒)でリセットして弾数を制御
shotTimer = boss.CeilingShotInterval;
}
if (timer <= 0f)
@@ -261,6 +267,7 @@ public class SpiderCeilingAttackState : SpiderStateBase
private void ExecuteRandomWebAttack()
{
// インスペクターで設定された半径(AttackRadius)を基準にランダム座標を計算
Vector2 randomCircle = Random.insideUnitCircle * boss.AttackRadius;
Vector3 targetGroundPos = new Vector3(
boss.groundAnchor.position.x + randomCircle.x,
@@ -268,10 +275,10 @@ public class SpiderCeilingAttackState : SpiderStateBase
boss.groundAnchor.position.z + randomCircle.y
);
boss.SpawnWarningAndWeb(targetGroundPos, 1.0f, 2.5f);
// ★リファクタリング:予兆マークのディレイや糸の生存時間もインスペクターと完全連動
boss.SpawnWarningAndWeb(targetGroundPos, boss.WebWarningDelay, boss.WebDuration);
}
}
public class SpiderStunState : SpiderStateBase
{
private float stunTimer;

View File

@@ -20,6 +20,9 @@ public class VRInputPunch : MonoBehaviour
[SerializeField] private float parryStunDuration = 3.0f; // スタン時間(秒)
[SerializeField] private float parryHapticAmplitude = 0.9f; // パリィ成功時の振動の強さ
[SerializeField] private float parryHapticDuration = 0.25f; // パリィ成功時の振動の長さ
// ─── 多段ヒット・連続暴発防止用タイマー ───
private float punchHitCooldown = 0f; // 次のパンチが当たるまでのインターバル
private float parryTriggerCooldown = 0f; // 次のパリィが成功するまでのインターバル
private void OnEnable()
{
@@ -51,40 +54,51 @@ public class VRInputPunch : MonoBehaviour
Vector3 velocity = velocityAction.action.ReadValue<Vector3>();
float speed = velocity.magnitude;
// ========================================================================
// 【パリィ判定】当たったオブジェクトが敵の拳だった場合
// ========================================================================
if (other.CompareTag("EnemyFist"))
{
Debug.Log($"🛡️ [パリィチェック] 敵の拳と接触。構え状態: {poseDetector.IsPosing}");
// 自分が「構え状態」のときだけパリィの成立チェックを行う
if (poseDetector.IsPosing)
{
// 1. ザコ敵(EnemyAI)へのパリィ判定
EnemyAI enemyAI = other.GetComponentInParent<EnemyAI>();
if (enemyAI != null)
{
enemyAI.TriggerParryStun(parryStunDuration);
TriggerHaptics(parryHapticAmplitude, parryHapticDuration);
Debug.Log($"🛡️ 【ジャストパリィ成功!】 敵の体勢を崩しました。スタン時間: {parryStunDuration}秒");
return;
Debug.Log($"🛡️ 【ジャストパリィ成功!】 敵の体勢を崩しました。");
return; // ★本当のパリィ成功時のみ、ここで処理を終了する
}
// 2. ボス(BossController)へのパリィ判定
BossController boss = other.GetComponentInParent<BossController>();
if (boss != null)
{
if(boss.TriggerParryStun())
// ★リファクタリング:ボスが本当に攻撃中(Bite/Charge)で、パリィが成功した時だけ終了する
if (boss.TriggerParryStun())
{
TriggerHaptics(parryHapticAmplitude, parryHapticDuration);
Debug.Log("🛡️ 【ジャストパリィ成功!】 ボスの体勢を崩しました!");
return;
TriggerHaptics(parryHapticAmplitude, parryHapticDuration);
Debug.Log("🛡️ 【ジャストパリィ成功!】 ボスの体勢を崩しました!");
return; // ★本当のパリィ成功時のみ、ここで処理を終了する
}
}
}
Debug.Log("🧱 ガード(構え不足):敵の攻撃は防いだが、弾き返せなかった。");
// ─── ★ここが今回の核心(超重要リファクタリング) ───
// 構え状態ではなかった場合、またはボスが攻撃中でなくパリィが不成立だった場合は、
// 「プレイヤーが隙を狙って殴りに行った」とみなして、returnせずにそのまま下のパンチ処理へ流す!
Debug.Log("🥊 パリィ不成立、または攻撃チャンス:通常のパンチダメージ処理へ移行します。");
}
// ────────────────────────────────────────────────────────────────────────
// パンチ攻撃の処理
// ========================================================================
// 【パンチ攻撃の処理】
// ========================================================================
Debug.Log($"[InputSystem接触] {other.name} に触れました。センサー速度: {speed:F2} m/s");
if (speed >= minPunchSpeed)