いろいろやってみた

Playerが蜘蛛にめり込まないようにしたい
This commit is contained in:
oogushiyuuga
2026-07-01 16:23:04 +09:00
parent 30ce9cbd0e
commit 4d3fee6ca5
473 changed files with 6618 additions and 24665 deletions

View File

@@ -0,0 +1,200 @@
using UnityEngine;
using UnityEngine.AI;
using System.Collections.Generic;
[RequireComponent(typeof(NavMeshAgent))]
[RequireComponent(typeof(Animator))]
public class BossController : MonoBehaviour
{
#region
[Header("ステータス設定")]
[SerializeField] private float maxHp = 500f;
[SerializeField] private float currentHp = 500f;
[SerializeField] public float chaseRange = 15f;
[SerializeField] public float biteRange = 2.5f;
[Header("必殺技(天井)設定")]
[Tooltip("天井の待機座標となる空のGameObjectのTransformを指定してください")]
[SerializeField] public Transform ceilingAnchor;
[Tooltip("地上に戻る際の、中央の着地座標のTransformを指定してください")]
[SerializeField] public Transform groundAnchor;
[Tooltip("天井から糸を発射する範囲の広さ")]
[SerializeField] public float attackRadius = 10f;
[Tooltip("糸が降る前の予兆マークのPrefab")]
[SerializeField] private GameObject warningMarkerPrefab;
[Tooltip("地面に残る糸コライダー鈍足スクリプト付きのPrefab")]
[SerializeField] private GameObject webPrefab;
[Header("突進(体当たり)設定")]
[SerializeField] public float chargeSpeed = 14f;
[SerializeField] public float chargeDuration = 2f;
[SerializeField] public float chargeMinimumDistance = 6f;
[SerializeField] public float chargeCooldownDuration = 4f;
#endregion
#region
[HideInInspector] public NavMeshAgent Agent { get; private set; }
[HideInInspector] public Animator Anim { get; private set; }
[HideInInspector] public Transform Player { get; private set; }
public float ChargeCooldownTimer { get; private set; } = 0f;
#endregion
#region FSM
private ISpiderState currentState;
// ステートのインスタンスをキャッシュ(ガベージコレクションの発生を抑える)
private Dictionary<System.Type, ISpiderState> stateCache;
// フェーズ管理用フラグ50%と25%のトリガー管理)
private bool triggered50 = false;
private bool triggered25 = false;
public bool PendingUltimate { get; set; } = false; // 必殺技の発動権があるか
#endregion
private void Awake()
{
Agent = GetComponent<NavMeshAgent>();
Anim = GetComponent<Animator>();
GameObject pObj = GameObject.FindGameObjectWithTag("Player");
if (pObj != null) Player = pObj.transform;
InitializeFSM();
}
private void InitializeFSM()
{
stateCache = new Dictionary<System.Type, ISpiderState>
{
{ typeof(SpiderIdleState), new SpiderIdleState(this) },
{ typeof(SpiderChaseState), new SpiderChaseState(this) },
{ typeof(SpiderBiteState), new SpiderBiteState(this) },
{ typeof(SpiderChargeState), new SpiderChargeState(this) },
{ typeof(SpiderJumpToCeilingState), new SpiderJumpToCeilingState(this) },
{ typeof(SpiderCeilingAttackState), new SpiderCeilingAttackState(this) },
{ typeof(SpiderStunState), new SpiderStunState(this) }
};
// 初期ステートをIdleに設定
ChangeState<SpiderIdleState>();
}
private void Update()
{
currentState?.UpdateState();
// ★新設突進のクールダウンのみ、通常のUpdateで常に独立して減算する
if (ChargeCooldownTimer > 0f)
{
ChargeCooldownTimer -= Time.deltaTime;
}
}
/// <summary>
/// オブジェクト指向に基づいた、型安全なステート遷移メソッド
/// </summary>
public void ChangeState<T>() where T : ISpiderState
{
if (currentState != null)
{
currentState.ExitState();
Debug.Log($"🕷️ BossSpider [Exit]: {currentState.GetType().Name}");
}
currentState = stateCache[typeof(T)];
Debug.Log($"🕷️ BossSpider [Enter]: {currentState.GetType().Name}");
currentState.EnterState();
}
/// <summary>
/// ダメージを受け取る外部窓口。HPトリガーによるフェーズ遷移をここで監視する
/// </summary>
public void TakeDamage(float damage)
{
currentHp -= damage;
currentHp = Mathf.Clamp(currentHp, 0, maxHp);
float hpPercentage = (currentHp / maxHp) * 100f;
Debug.Log($"💥 ボスに {damage} ダメージ。残りHP: {hpPercentage:F1}%");
// 25%以下カットのトリガー
if (hpPercentage <= 25f && !triggered25)
{
triggered25 = true;
PendingUltimate = true;
TriggerPhaseTransition();
}
// 50%以下カットのトリガー
else if (hpPercentage <= 50f && !triggered50 && hpPercentage > 25f)
{
triggered50 = true;
PendingUltimate = true;
TriggerPhaseTransition();
}
}
private void TriggerPhaseTransition()
{
// 咆哮、ジャンプ、スタン中以外であれば、現在の行動をキャンセルして即座に天井へエスケープ
if (currentState is not SpiderJumpToCeilingState &&
currentState is not SpiderCeilingAttackState &&
currentState is not SpiderStunState)
{
ChangeState<SpiderJumpToCeilingState>();
}
}
/// <summary>
/// 【パリィ連携窓口】プレイヤーのVRInputPunchなどから、パリィ成功時にこのメソッドが叩かれる
/// </summary>
public void TriggerParryStun()
{
// パリィを受け付ける攻撃ステート(噛みつき、体当たり)のときのみスタンに移行する
if (currentState is SpiderBiteState || currentState is SpiderChargeState)
{
ChangeState<SpiderStunState>();
}
}
public void ResetChargeCooldown()
{
ChargeCooldownTimer = chargeCooldownDuration;
}
#region
public void SpawnWarningAndWeb(Vector3 targetGroundPos, float delay, float webDuration)
{
StartCoroutine(SpawnWebRoutine(targetGroundPos, delay, webDuration));
}
private System.Collections.IEnumerator SpawnWebRoutine(Vector3 pos, float delay, float duration)
{
// 1. 地面に予兆マークを生成
GameObject marker = null;
if (warningMarkerPrefab != null)
{
marker = Instantiate(warningMarkerPrefab, pos + new Vector3(0, 0.02f, 0), Quaternion.identity);
}
yield return new WaitForSeconds(delay);
// 2. 予兆マークを消し、本物の糸オブジェクトを生成
if (marker != null) Destroy(marker);
if (webPrefab != null)
{
GameObject web = Instantiate(webPrefab, pos, Quaternion.identity);
Destroy(web, duration); // 数秒後に自動消滅
}
}
#endregion
}
#region 1.
public interface ISpiderState
{
void EnterState();
void UpdateState();
void ExitState();
}
#endregion