docs(10_Wiki): Topic_Business/General/Graphic/Programming을 Topics/ 하위로 이동
최상위 10_Wiki/Topic_*였던 4개 카테고리 폴더를 10_Wiki/Topics/Topic_* 로 재배치. 콘텐츠 변경 없음(순수 폴더 이동) — Topics/ 하위 나머지 폴더는 이미 지난 커밋에서 전부 정리된 상태(잔존 항목은 에이전트 운영 상태 및 사용자가 보존을 요청한 업데이트0615/무제 3.canvas 뿐).
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
---
|
||||
id: wiki-2026-0508-포탑-시스템-turret-systems
|
||||
title: 포탑 시스템(Turret Systems)
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [Turret Systems, Tower Defense, Auto-targeting]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.85
|
||||
verification_status: applied
|
||||
tags: [game-design, ai, gameplay, tower-defense]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
tech_stack:
|
||||
language: C# / GDScript
|
||||
framework: Unity / Godot
|
||||
---
|
||||
|
||||
# 포탑 시스템(Turret Systems)
|
||||
|
||||
## 매 한 줄
|
||||
> **"매 stationary defender 의 자동 target 의 acquisition + tracking + firing."**. 매 1980s arcade (Missile Command) 부터 매 modern tower defense (Bloons TD 6, PvZ), 매 RTS (StarCraft 의 turret), 매 FPS (Team Fortress 2 의 sentry) 의 universal mechanic. 매 target selection + range + cooldown + projectile 의 4-axis design.
|
||||
|
||||
## 매 핵심
|
||||
|
||||
### 매 component
|
||||
- **Target acquisition**: 매 range 내 enemy 의 detection — sphere/cone overlap.
|
||||
- **Target selection**: 매 closest / lowest HP / highest threat / first / last 의 priority.
|
||||
- **Aim / tracking**: 매 turret 의 rotation 의 slerp / lerp.
|
||||
- **Firing**: 매 cooldown + projectile spawn / hitscan.
|
||||
- **Upgrade tree**: 매 damage / range / fire rate / special 의 progression.
|
||||
|
||||
### 매 design axis
|
||||
- **Range**: 매 short (high DPS) vs long (low DPS) 의 tradeoff.
|
||||
- **AoE**: 매 splash damage — 매 group 의 효과적.
|
||||
- **Status**: 매 slow / burn / poison 의 debuff.
|
||||
- **Projectile**: 매 hitscan vs ballistic — 매 leading prediction 의 필요.
|
||||
- **Cost / placement**: 매 economic + spatial constraint.
|
||||
|
||||
### 매 응용
|
||||
1. **Tower defense**: 매 wave 의 incremental difficulty.
|
||||
2. **RTS**: 매 base defense 의 layer.
|
||||
3. **FPS**: 매 area denial 의 device.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### Unity 의 turret base
|
||||
```csharp
|
||||
public class Turret : MonoBehaviour
|
||||
{
|
||||
public float range = 10f;
|
||||
public float fireRate = 1f;
|
||||
public Transform muzzle;
|
||||
public GameObject projectile;
|
||||
|
||||
private Transform target;
|
||||
private float cooldown;
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (target == null || Vector3.Distance(transform.position, target.position) > range)
|
||||
target = FindTarget();
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
AimAt(target);
|
||||
cooldown -= Time.deltaTime;
|
||||
if (cooldown <= 0f) { Fire(); cooldown = 1f / fireRate; }
|
||||
}
|
||||
}
|
||||
|
||||
Transform FindTarget()
|
||||
{
|
||||
Collider[] hits = Physics.OverlapSphere(transform.position, range, LayerMask.GetMask("Enemy"));
|
||||
return hits.OrderBy(c => Vector3.Distance(transform.position, c.transform.position))
|
||||
.FirstOrDefault()?.transform;
|
||||
}
|
||||
|
||||
void AimAt(Transform t)
|
||||
{
|
||||
Vector3 dir = (t.position - transform.position).normalized;
|
||||
Quaternion target = Quaternion.LookRotation(dir);
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * 8f);
|
||||
}
|
||||
|
||||
void Fire()
|
||||
{
|
||||
Instantiate(projectile, muzzle.position, muzzle.rotation);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Target priority strategy
|
||||
```csharp
|
||||
public enum Priority { Closest, Lowest, Highest, First, Last }
|
||||
|
||||
Transform FindTarget(Priority p)
|
||||
{
|
||||
var enemies = Physics.OverlapSphere(transform.position, range, enemyLayer)
|
||||
.Select(c => c.GetComponent<Enemy>()).Where(e => e != null);
|
||||
|
||||
return p switch
|
||||
{
|
||||
Priority.Closest => enemies.OrderBy(e => Vector3.Distance(transform.position, e.transform.position)).FirstOrDefault()?.transform,
|
||||
Priority.Lowest => enemies.OrderBy(e => e.HP).FirstOrDefault()?.transform,
|
||||
Priority.Highest => enemies.OrderByDescending(e => e.HP).FirstOrDefault()?.transform,
|
||||
Priority.First => enemies.OrderByDescending(e => e.PathProgress).FirstOrDefault()?.transform,
|
||||
Priority.Last => enemies.OrderBy(e => e.PathProgress).FirstOrDefault()?.transform,
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Ballistic leading
|
||||
```csharp
|
||||
// 매 moving target 의 prediction
|
||||
Vector3 PredictAimPoint(Vector3 targetPos, Vector3 targetVel, float projectileSpeed)
|
||||
{
|
||||
Vector3 toTarget = targetPos - muzzle.position;
|
||||
float a = Vector3.Dot(targetVel, targetVel) - projectileSpeed * projectileSpeed;
|
||||
float b = 2f * Vector3.Dot(targetVel, toTarget);
|
||||
float c = Vector3.Dot(toTarget, toTarget);
|
||||
float disc = b * b - 4f * a * c;
|
||||
if (disc < 0f) return targetPos;
|
||||
float t = (-b - Mathf.Sqrt(disc)) / (2f * a);
|
||||
return targetPos + targetVel * t;
|
||||
}
|
||||
```
|
||||
|
||||
### AoE projectile
|
||||
```csharp
|
||||
public class ExplosiveProjectile : MonoBehaviour
|
||||
{
|
||||
public float radius = 3f;
|
||||
public float damage = 50f;
|
||||
|
||||
void OnCollisionEnter(Collision col)
|
||||
{
|
||||
foreach (var c in Physics.OverlapSphere(transform.position, radius, enemyLayer))
|
||||
{
|
||||
float dist = Vector3.Distance(transform.position, c.transform.position);
|
||||
float falloff = 1f - dist / radius;
|
||||
c.GetComponent<Enemy>()?.TakeDamage(damage * falloff);
|
||||
}
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Upgrade tree (ScriptableObject)
|
||||
```csharp
|
||||
[CreateAssetMenu]
|
||||
public class TurretUpgrade : ScriptableObject
|
||||
{
|
||||
public string displayName;
|
||||
public int cost;
|
||||
public float damageMultiplier = 1f;
|
||||
public float rangeMultiplier = 1f;
|
||||
public float fireRateMultiplier = 1f;
|
||||
public TurretUpgrade[] nextChoices;
|
||||
}
|
||||
```
|
||||
|
||||
### Godot 의 turret (GDScript)
|
||||
```gdscript
|
||||
extends Node3D
|
||||
|
||||
@export var range: float = 10.0
|
||||
@export var fire_rate: float = 1.0
|
||||
var cooldown := 0.0
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
var target := _find_target()
|
||||
if target:
|
||||
look_at(target.global_position, Vector3.UP)
|
||||
cooldown -= delta
|
||||
if cooldown <= 0:
|
||||
_fire()
|
||||
cooldown = 1.0 / fire_rate
|
||||
|
||||
func _find_target() -> Node3D:
|
||||
var space := get_world_3d().direct_space_state
|
||||
var query := PhysicsShapeQueryParameters3D.new()
|
||||
var shape := SphereShape3D.new()
|
||||
shape.radius = range
|
||||
query.shape = shape
|
||||
query.transform = global_transform
|
||||
query.collision_mask = 2 # enemy layer
|
||||
var hits := space.intersect_shape(query)
|
||||
return hits[0].collider if hits else null
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 매 tower defense | Closest / First priority + AoE |
|
||||
| 매 RTS base defense | Highest HP / threat priority |
|
||||
| 매 boss arena | Lowest HP focus fire |
|
||||
| 매 fast enemy | Hitscan + slow status |
|
||||
| 매 swarm | AoE + chain lightning |
|
||||
| 매 armored | Pierce / true damage |
|
||||
|
||||
**기본값**: 매 tower defense — Closest priority, ballistic projectile, 3-tier upgrade tree, $50-200 cost range.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Game Mechanics]]
|
||||
- 변형: [[Tower Defense]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 turret upgrade tree 의 brainstorm, 매 balance spreadsheet 의 generation, 매 priority logic 의 review.
|
||||
**언제 X**: 매 production combat tuning — 매 playtest data + analytics 의 우선.
|
||||
|
||||
## 매 안티패턴
|
||||
- **Single priority**: 매 closest only — 매 player choice 의 부재.
|
||||
- **No leading**: 매 fast enemy 의 ballistic miss — 매 prediction 의 누락.
|
||||
- **Linear upgrade**: 매 X% damage 의 monotone — 매 build diversity 의 부재.
|
||||
- **Cost imbalance**: 매 best turret 의 always cheapest — 매 dominant strategy.
|
||||
- **No counter**: 매 single tower 의 모든 enemy 의 처치 — 매 strategic depth 의 부재.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Bloons TD 6 design retrospective, GDC talks, Unity / Godot docs).
|
||||
- 신뢰도 A-.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — turret components + Unity/Godot patterns |
|
||||
Reference in New Issue
Block a user