Files
VRProject/Assets/_Scripts/SpiderIdleState.cs
oogushiyuuga ae74d4b279 もろもろ
Warningprefabを追加
Hpゲージの選定
ボスの攻撃判定を改善
2026-07-17 12:29:03 +09:00

358 lines
11 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;
public class SpiderIdleState : SpiderStateBase
{
public SpiderIdleState(BossController owner) : base(owner) { }
public override void EnterState() => boss.Anim.SetTrigger("Idle");
public override void UpdateState()
{
if (boss.Player == null) return;
if (Vector3.Distance(boss.transform.position, boss.Player.position) <= boss.ChaseRange)
{
boss.ChangeState<SpiderChaseState>();
}
}
}
public class SpiderChaseState : SpiderStateBase
{
public SpiderChaseState(BossController owner) : base(owner) { }
public override void EnterState() => boss.Agent.isStopped = false;
public override void UpdateState()
{
if (boss.Player == null) return;
float distance = Vector3.Distance(boss.transform.position, boss.Player.position);
// 遠距離突進判定(カプセル化されたプロパティを使用)
if (distance >= boss.ChargeMinimumDistance && boss.ChargeCooldownTimer <= 0f)
{
boss.ChangeState<SpiderChargeState>();
return;
}
// 至近距離噛みつき判定
if (distance <= boss.BiteRange)
{
boss.ChangeState<SpiderBiteState>();
return;
}
boss.Agent.SetDestination(boss.Player.position);
boss.Anim.SetFloat("Speed", boss.Agent.velocity.magnitude);
}
}
public class SpiderBiteState : SpiderStateBase
{
private float stateTimer;
private const float TurnSpeed = 4f;
public SpiderBiteState(BossController owner) : base(owner) { }
public override void EnterState()
{
stateTimer = 1.5f;
boss.Agent.ResetPath();
boss.Agent.isStopped = true;
boss.Agent.velocity = Vector3.zero;
boss.Anim.SetFloat("Speed", 0f);
boss.Anim.SetTrigger("Attack_Bite");
Debug.Log("🎯 蜘蛛ボス:通常噛みつき開始。攻撃モーション中にゆっくり向き直ります。");
}
public override void ExitState()
{
boss.Agent.isStopped = false;
}
public override void UpdateState()
{
boss.Agent.velocity = Vector3.zero;
if (boss.Player != null)
{
Vector3 lookDir = (boss.Player.position - boss.transform.position).normalized;
lookDir.y = 0;
if (lookDir != Vector3.zero)
{
boss.transform.rotation = Quaternion.Slerp(
boss.transform.rotation,
Quaternion.LookRotation(lookDir),
Time.deltaTime * TurnSpeed
);
}
}
stateTimer -= Time.deltaTime;
if (stateTimer <= 0f)
{
if (boss.PendingUltimate) boss.ChangeState<SpiderJumpToCeilingState>();
else boss.ChangeState<SpiderChaseState>();
}
}
}
public class SpiderChargeState : SpiderStateBase
{
private float roarTimer;
private float chargeTimer;
private Vector3 chargeDirection;
private bool isChargingPhase;
public SpiderChargeState(BossController owner) : base(owner) { }
public override void EnterState()
{
roarTimer = boss.ChargeRoarDuration;
chargeTimer = boss.ChargeDuration;
isChargingPhase = false;
boss.Agent.isStopped = true;
boss.Agent.velocity = Vector3.zero;
boss.ResetChargeCooldown();
boss.Anim.SetTrigger("Attack_Roar");
Debug.Log($"🔊 蜘蛛ボス:遠距離を検知。その場でピタッと完全停止。咆哮(溜め {roarTimer}秒)を開始!");
}
public override void ExitState()
{
boss.Anim.SetBool("IsCharging", false);
boss.Agent.speed = boss.NormalSpeed;
boss.Agent.acceleration = boss.NormalAcceleration;
boss.Agent.isStopped = false;
}
public override void UpdateState()
{
// フェーズ1咆哮・溜めロックオン
if (!isChargingPhase)
{
roarTimer -= Time.deltaTime;
boss.Agent.velocity = Vector3.zero; // 完全固定
if (boss.Player != null)
{
Vector3 lookDir = (boss.Player.position - boss.transform.position).normalized;
lookDir.y = 0;
if (lookDir != Vector3.zero)
{
boss.transform.rotation = Quaternion.Slerp(boss.transform.rotation, Quaternion.LookRotation(lookDir), Time.deltaTime * 10f);
}
}
if (roarTimer <= 0f)
{
isChargingPhase = true;
boss.Anim.SetTrigger("ChargeStart");
boss.Anim.SetBool("IsCharging", true);
if (boss.Player != null)
{
chargeDirection = (boss.Player.position - boss.transform.position).normalized;
chargeDirection.y = 0;
}
Vector3 targetDestination = boss.transform.position + chargeDirection * 20f;
boss.Agent.isStopped = false;
boss.Agent.speed = boss.ChargeSpeed;
boss.Agent.acceleration = 120f;
boss.Agent.SetDestination(targetDestination);
Debug.Log("🚀 蜘蛛ボス:ロックオン完了。全速力で突進ダッシュを発射!");
}
return;
}
// フェーズ2突進移動中
chargeTimer -= Time.deltaTime;
if (chargeTimer <= 0f || (boss.Agent.velocity.magnitude < 0.2f && chargeTimer < (boss.ChargeDuration - 0.3f)))
{
boss.ChangeState<SpiderChaseState>();
}
}
}
public class SpiderJumpToCeilingState : SpiderStateBase
{
private float roarTimer;
private float jumpProgress;
private Vector3 startPos;
private bool isJumpingPhase;
public SpiderJumpToCeilingState(BossController owner) : base(owner) { }
public override void EnterState()
{
roarTimer = boss.JumpRoarDuration;
jumpProgress = 0f;
startPos = boss.transform.position;
isJumpingPhase = false;
boss.Agent.enabled = false;
boss.Anim.SetTrigger("Attack_Roar");
Debug.Log($"🚨 蜘蛛ボス:必殺技前の一大威嚇(咆哮 {roarTimer}秒)!");
}
public override void UpdateState()
{
// フェーズ1飛び立つ前の威嚇
if (!isJumpingPhase)
{
roarTimer -= Time.deltaTime;
if (roarTimer <= 0f)
{
isJumpingPhase = true;
boss.Anim.SetTrigger("JumpUp");
}
return;
}
// フェーズ2ジャンプ空中移動
if (boss.ceilingAnchor == null) return;
jumpProgress += Time.unscaledDeltaTime * 1.5f;
Vector3 currentPos = Vector3.Lerp(startPos, boss.ceilingAnchor.position, jumpProgress);
currentPos.y += Mathf.Sin(jumpProgress * Mathf.PI) * 3f;
boss.transform.position = currentPos;
if (jumpProgress >= 1f)
{
boss.transform.position = boss.ceilingAnchor.position;
boss.ChangeState<SpiderCeilingAttackState>();
}
}
}
// ==========================================
// ■ STATE: CEILING ATTACK (インスペクター無段階調整版)
// ==========================================
public class SpiderCeilingAttackState : SpiderStateBase
{
private float timer = 0f;
private float shotTimer = 0f;
public SpiderCeilingAttackState(BossController owner) : base(owner) { }
public override void EnterState()
{
// ★リファクタリング:インスペクターで設定した必殺技の長さを適用
timer = boss.CeilingAttackDuration;
shotTimer = 0f;
boss.Anim.SetBool("IsOnCeiling", true);
boss.PendingUltimate = false;
Debug.Log($"🕸️ 蜘蛛ボス:天井からの乱射開始! 持続時間: {timer}秒 / 発射間隔: {boss.CeilingShotInterval}秒");
}
public override void ExitState()
{
boss.Anim.SetBool("IsOnCeiling", false);
if (boss.groundAnchor != null) boss.transform.position = boss.groundAnchor.position;
boss.Agent.enabled = true;
boss.Anim.SetTrigger("Land");
}
public override void UpdateState()
{
timer -= Time.deltaTime;
shotTimer -= Time.deltaTime;
// タイマーがゼロになったら発射
if (shotTimer <= 0f)
{
ExecuteRandomWebAttack();
// ★リファクタリング:インスペクターで設定した間隔(秒)でリセットして弾数を制御
shotTimer = boss.CeilingShotInterval;
}
if (timer <= 0f)
{
boss.ChangeState<SpiderChaseState>();
}
}
private void ExecuteRandomWebAttack()
{
Vector3 targetGroundPos = Vector3.zero;
int maxAttempts = 15; // 無限ループ(フリーズ)を防止するための最大再抽選回数
for (int i = 0; i < maxAttempts; i++)
{
// 1. 一旦ランダムな座標を算出
Vector2 randomCircle = Random.insideUnitCircle * boss.AttackRadius;
targetGroundPos = new Vector3(
boss.groundAnchor.position.x + randomCircle.x,
boss.groundAnchor.position.y,
boss.groundAnchor.position.z + randomCircle.y
);
// 2. 現在アクティブなすべての糸との距離を計測する
bool isTooClose = false;
foreach (Vector3 existingPos in boss.ActiveWebPositions)
{
// 設定された回避半径WebAvoidanceRadiusより近い既存の糸があるか
if (Vector3.Distance(targetGroundPos, existingPos) < boss.WebAvoidanceRadius)
{
isTooClose = true;
break; // 被り検知、この座標は使えないのでチェックを抜けて再抽選へ
}
}
// 3. 誰とも被っていなければ、このクリーンな座標で確定
if (!isTooClose)
{
break;
}
}
// 確定した(または上限に達して安全が担保された)座標へ向けて発射命令
boss.SpawnWarningAndWeb(targetGroundPos, boss.WebWarningDelay, boss.WebDuration);
}
}
public class SpiderStunState : SpiderStateBase
{
private float stunTimer;
public SpiderStunState(BossController owner) : base(owner) { }
public override void EnterState()
{
stunTimer = 4.0f;
boss.Anim.SetTrigger("StunStart");
boss.Anim.SetBool("IsStunned", true);
if (boss.Agent.enabled) boss.Agent.isStopped = true;
Debug.Log("🛡️ パリィ成功! チャンスタイム!");
}
public override void ExitState()
{
boss.Anim.SetBool("IsStunned", false);
if (boss.Agent.enabled) boss.Agent.isStopped = false;
}
public override void UpdateState()
{
stunTimer -= Time.deltaTime;
if (stunTimer <= 0f)
{
if (boss.PendingUltimate) boss.ChangeState<SpiderJumpToCeilingState>();
else boss.ChangeState<SpiderChaseState>();
}
}
}