@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user