Files
VRProject/Assets/_Scripts/SpiderIdleState.cs
ohgushiyuga 52341100ed otamesi
2026-08-27 12:51:15 +09:00

350 lines
9.4 KiB
C#

using UnityEngine;
public interface ISpiderState
{
void EnterState();
void UpdateState();
void ExitState();
}
public abstract class SpiderStateBase : ISpiderState
{
protected readonly BossController boss;
protected SpiderStateBase(BossController owner)
{
boss = owner;
}
public virtual void EnterState() { }
public abstract void UpdateState();
public virtual void ExitState() { }
}
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");
}
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");
}
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()
{
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);
}
return;
}
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");
}
public override void UpdateState()
{
if (!isJumpingPhase)
{
roarTimer -= Time.deltaTime;
if (roarTimer <= 0f)
{
isJumpingPhase = true;
boss.Anim.SetTrigger("JumpUp");
}
return;
}
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>();
}
}
}
public class SpiderCeilingAttackState : SpiderStateBase
{
private float timer;
private float shotTimer;
public SpiderCeilingAttackState(BossController owner) : base(owner) { }
public override void EnterState()
{
timer = boss.CeilingAttackDuration;
shotTimer = 0f;
boss.Anim.SetBool("IsOnCeiling", true);
boss.PendingUltimate = false;
}
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++)
{
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
);
bool isTooClose = false;
foreach (Vector3 existingPos in boss.WebSpawner.ActiveWebPositions)
{
if (Vector3.Distance(targetGroundPos, existingPos) < boss.WebSpawner.WebAvoidanceRadius)
{
isTooClose = true;
break;
}
}
if (!isTooClose) break;
}
boss.WebSpawner.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;
}
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>();
}
}
}