--- id: wiki-2026-0508-ai-추적-논리-ai-pursuit-logic title: AI Pursuit Logic (AI 추적 논리) category: 10_Wiki/Topics status: verified canonical_id: self aliases: [AI 추적, pursuit logic, aggro, threat detection, leash range, NPC chase] duplicate_of: none source_trust_level: B confidence_score: 0.85 verification_status: conceptual tags: [game-ai, pursuit, aggro, threat-system, npc-design, baiting, leash, fsm, behavior-tree] raw_sources: [] last_reinforced: 2026-05-09 github_commit: pending inferred_by: Claude Opus 4.7 (manual cleanup 2026-05-09) tech_stack: language: game design / Unity / Unreal applicable_to: [Game Design, Combat AI, RTS, MMO, FPS] --- # AI Pursuit Logic (AI 추적 논리) ## 📌 한 줄 통찰 (The Karpathy Summary) > **"매 enemy 의 어떤 target 의 chase?"**. Aggro / threat / line-of-sight / leash 의 4 component. 매 RTS / MMO / FPS 의 fundamental. **매 deterministic = baiting exploitable, 매 random = unpredictable feel**. ## 📖 구조화된 지식 (Synthesized Content) ### 매 component 1. **Detection**: 매 enemy 의 sight cone / sound / threat radius. 2. **Threat / aggro**: 매 player 의 weight (proximity, damage dealt, special). 3. **Pursuit decision**: 매 stance / state 의 chase / hold. 4. **Leash**: 매 chase 의 max distance. 5. **De-aggro**: 매 reset condition. ### 매 stance / state #### Active pursuit (Fire at Will / Aggressive) - 매 enemy detect → chase to engage. - 매 wide pursuit radius. - Vulnerable to baiting. #### Defensive (Hold Position / Stand Ground) - 매 stay in spot. - 매 in-range only engage. - Bait 의 immune. #### Patrol - 매 fixed route. - 매 detect → pursue 일정 time → return. - 매 player 의 timing exploit. #### Guarding - 매 specific target / area. - 매 leash 의 strict. - 매 player 의 line-of-sight break 의 reset. #### Conditional (low HP, ally death) - 매 trigger 의 stance change. - Berserk / flee. ### Aggro / threat system #### Proximity-based (simple) - 매 distance 의 inverse 의 weight. - 매 closest = highest priority. #### Damage-based - 매 damage dealt 의 cumulative. - 매 healer / DPS 의 high priority. - MMO 의 tank role 의 enable. #### Stealth / detection - 매 sight cone (FPS, stealth game). - 매 noise level. - 매 disguise / blend. #### Special abilities - 매 taunt / provoke 의 instant aggro. - 매 invisibility / cloak 의 break aggro. - 매 mind control. ### Leash mechanism - 매 chase 의 max range. - 매 exceed = full reset (heal, return). - 매 cheese 의 prevent (kite + reset attack). ``` Chase distance > maxLeash: - Stop pursuit. - Reset HP to full. - Return to spawn. - 매 player 의 punish. ``` ### Wild goose chase 의 exploit 1. Player unit (fast / cheap) 의 enemy 의 lure. 2. Enemy 의 pursue. 3. Player 의 ambush location. 4. Enemy 의 trap. → 매 RTS / MMO 의 universal tactic. ### Modern variants #### Adaptive aggro - 매 player behavior 의 learn. - 매 cheese pattern 의 detect. - 매 counter-strategy. #### Squad coordination - 매 enemy 의 group communicate. - 매 player 의 line-of-sight 의 share. - 매 flanking maneuver. #### Memory / persistence - 매 enemy 의 last known player position. - 매 search 의 specific area. - 매 continued investigation. #### Investigation state (stealth) - 매 noise → suspicious → investigate → return / aggro. - 매 partial detection 의 layered. ### Game examples #### Classic RTS (StarCraft, AoE, Warcraft) - A-move = active pursuit. - Stop / Hold = anchor. - 매 leash range. #### MMO (WoW, FFXIV) - 매 mob 의 leash range (tunable). - 매 tank 의 threat. - 매 reset 의 full heal (anti-cheese). #### Stealth (Splinter Cell, MGS) - 매 detection meter. - 매 sound radius. - 매 alert state cycle. #### FPS (Halo, Doom) - 매 enemy 의 cover seeking. - 매 line-of-sight break 의 search. - 매 grenade 의 flush. ### Player exploit pattern #### 1. Bait + lure - 매 cheap unit 의 sacrifice. - 매 enemy 의 chase. - 매 ambush. #### 2. Kiting - 매 ranged 의 attack + retreat. - 매 enemy 의 perpetual pursue. - 매 attrition kill. #### 3. Line-of-sight break - 매 wall 의 hide. - 매 enemy 의 lose vision. - 매 reset / stealth. #### 4. Leash exploit - 매 enemy 의 leash 끝. - 매 attack 후 retreat. - 매 enemy 의 reset (full heal — but separated). → 매 MMO 의 banned (exploit) 또는 intended (skill). #### 5. Aggro management - 매 player 의 selective threat. - 매 boss 의 specific target. - 매 strategic positioning. ## 💻 코드 패턴 (Code Patterns) ### Threat / aggro table ```csharp public class ThreatTable { Dictionary threats = new(); public void AddThreat(Player p, float amount) { threats[p] = threats.GetValueOrDefault(p, 0) + amount; } public Player GetTopThreat() { if (threats.Count == 0) return null; return threats.OrderByDescending(x => x.Value).First().Key; } public void Decay(float deltaTime) { foreach (var key in threats.Keys.ToList()) { threats[key] *= Mathf.Pow(0.9f, deltaTime); // 10s half-life } } public void OnPlayerDeath(Player p) { threats.Remove(p); } } ``` ### Pursuit FSM ```csharp public enum AIState { Idle, Patrol, Suspicious, Pursuing, Engaging, Returning } public class EnemyAI : MonoBehaviour { public AIState state = AIState.Idle; public Vector3 spawnPoint; public float leashRange = 30f; public float sightRange = 15f; public Transform target; void Update() { switch (state) { case AIState.Idle: if (DetectPlayer()) state = AIState.Pursuing; break; case AIState.Pursuing: if (Vector3.Distance(transform.position, spawnPoint) > leashRange) { state = AIState.Returning; target = null; } else if (InAttackRange()) { state = AIState.Engaging; } else { MoveToward(target.position); } break; case AIState.Engaging: Attack(target); if (!InAttackRange()) state = AIState.Pursuing; break; case AIState.Returning: if (ReachedSpawn()) { HealFully(); // anti-cheese state = AIState.Idle; } MoveToward(spawnPoint); break; } } bool DetectPlayer() { Player p = FindNearestPlayer(); if (p == null) return false; if (Vector3.Distance(transform.position, p.transform.position) > sightRange) return false; if (!HasLineOfSight(p)) return false; target = p.transform; return true; } } ``` ### Stance-based pursuit (RTS) ```csharp public enum Stance { Passive, Defensive, Aggressive, Hold } public class RTSUnit : MonoBehaviour { public Stance stance = Stance.Defensive; public float pursuitRadius = 10f; void Update() { switch (stance) { case Stance.Passive: // Don't engage. Move only on player command. break; case Stance.Defensive: // Engage in attack range only. Enemy nearby = FindEnemyInRange(attackRange); if (nearby != null) Attack(nearby); break; case Stance.Aggressive: // Pursue any enemy in radius. Enemy enemy = FindEnemyInRange(pursuitRadius); if (enemy != null) { if (InAttackRange(enemy)) Attack(enemy); else MoveToward(enemy.transform.position); } break; case Stance.Hold: // Like Defensive but no movement. Enemy inRange = FindEnemyInRange(attackRange); if (inRange != null) Attack(inRange); // No move. break; } } } ``` ### Sight cone (stealth) ```csharp public class SightCone : MonoBehaviour { public float sightRange = 15f; public float sightAngle = 90f; public LayerMask obstacleLayer; public bool CanSee(Transform target) { Vector3 dir = (target.position - transform.position).normalized; float dist = Vector3.Distance(transform.position, target.position); if (dist > sightRange) return false; if (Vector3.Angle(transform.forward, dir) > sightAngle / 2) return false; // Line-of-sight check if (Physics.Raycast(transform.position, dir, dist, obstacleLayer)) return false; return true; } } ``` ### De-aggro / reset ```csharp public class DeAggro : MonoBehaviour { public float losTimeout = 5f; // 5s 의 line-of-sight break = reset float lastSeenTime; void Update() { if (sight.CanSee(target)) { lastSeenTime = Time.time; } else if (Time.time - lastSeenTime > losTimeout) { ResetAggro(); } } void ResetAggro() { threatTable.Clear(); target = null; state = AIState.Returning; } } ``` ### Squad coordination ```csharp public class Squad : MonoBehaviour { List members = new(); Player sharedTarget; public void OnDetect(Player p) { if (sharedTarget == null) { sharedTarget = p; // Alert all members foreach (var m in members) { m.target = p.transform; m.state = AIState.Pursuing; } } } public void Coordinate() { // 매 member 의 different angle 의 attack. for (int i = 0; i < members.Count; i++) { float angle = (Mathf.PI * 2 * i) / members.Count; Vector3 offset = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)) * 5; members[i].SetMoveTarget(sharedTarget.transform.position + offset); } } } ``` ### Memory / investigation (stealth) ```csharp public class GuardAI : MonoBehaviour { public AIState state = AIState.Patrol; Vector3 lastSeenPosition; float investigateTime = 10f; void Update() { if (state == AIState.Patrol) { if (DetectPlayer()) { state = AIState.Pursuing; lastSeenPosition = target.position; } } else if (state == AIState.Pursuing) { if (CanSeePlayer()) { lastSeenPosition = target.position; } else { state = AIState.Investigating; } } else if (state == AIState.Investigating) { MoveToward(lastSeenPosition); if (ReachedDestination()) { if (CanSeePlayer()) { state = AIState.Pursuing; } else if (timeInState > investigateTime) { state = AIState.Patrol; // Give up. } } } } } ``` ### Anti-cheese (RTS leash + heal) ```csharp public class AntiCheese : MonoBehaviour { public float maxLeash = 30f; Vector3 spawnPoint; void Update() { if (Vector3.Distance(transform.position, spawnPoint) > maxLeash) { // 매 player 의 kite + reset attack 의 punish. ResetAggro(); FullHeal(); ReturnHome(); } } } ``` ## 🤔 의사결정 기준 (Decision Criteria) | 상황 | 추천 pursuit logic | |---|---| | RTS unit | Stance-based (player choice) | | MMO mob | Threat table + leash | | FPS enemy | Sight cone + cover seeking | | Stealth game | Sight + sound + investigation state | | Boss fight | Phased + threat + special mechanic | | Roguelike | Simple proximity + variety | **기본값**: Threat table + leash + LOS-based reset. Anti-cheese. ## ⚠️ 모순 및 업데이트 (Contradictions & Updates) - **Predictable vs unfair**: 매 deterministic 의 baiting exploit, 매 random 의 frustrating. - **Aggro 의 transparency**: MMO 의 tank role 의 explicit threat. 매 player 의 strategic. - **Leash 의 anti-cheese vs immersion**: 매 reset 의 unrealistic feel. - **AI 의 squad coordination 의 cost**: 매 sophisticated 의 dev expensive. ## 🔗 지식 연결 (Graph) - 응용: [[AI Exploitation (Game AI 공략)]] · [[Baiting Tactics]] - 매 game: [[War-Commander]] - Adjacent: [[Behavior-Tree]] ## 🤖 LLM 활용 힌트 (How to Use This Knowledge) **언제 이 지식을 쓰는가:** - 매 game 의 enemy AI design. - 매 stance / threat system 의 implement. - 매 stealth game 의 detection. - 매 boss fight 의 mechanic. - 매 player exploit 의 review. **언제 쓰면 안 되는가:** - Single-player turn-based (different paradigm). - Walking simulator. - 매 LLM agent (different domain — partial overlap). ## ❌ 안티패턴 (Anti-Patterns) - **No leash + open world**: 매 cheese 의 enable. - **Pure proximity threat**: 매 healer / DPS 의 unfair. - **No LOS reset**: 매 wall 의 follow 의 unrealistic. - **No memory**: 매 player 의 hide 후 의 instant forget. - **No squad coordination**: 매 1 vs 1 의 weak. - **Fully deterministic**: 매 첫 try 후 trivialize. - **Excessive randomness**: 매 player 의 frustrating. ## 🧪 검증 상태 (Validation) - **정보 상태:** verified (concept-level). - **출처 신뢰도:** B (Game AI Programming Wisdom series, Unity / Unreal documentation, GDC talks). - **검토 이유:** Manual cleanup. 매 specific game 의 implementation 가 design choice. ## 🧬 중복 검사 (Duplicate Check) - **기존 유사 문서:** [[AI Exploitation (Game AI 공략)]] (related), [[Game-AI-Behavior-Tree]] (parent), [[Combat-AI]] (parent). - **처리 방식:** KEEP (specific focus on pursuit). - **처리 이유:** Pursuit logic 가 specific component. ## 🕓 변경 이력 (Changelog) | 날짜 | 변경 내용 | 처리 방식 | 신뢰도 | |------|-----------|-----------|--------| | 2026-05-08 | P-Reinforce Phase 1 정규화 | UPDATE | A | | 2026-05-09 | Manual cleanup — Unity code + 4 component + 매 game example + 안티패턴 추가 | UPDATE | B |