모든 SceneView 배치 조작에 Undo/Redo 지원 (Undo.RecordObject)
3.3 시뮬레이션 모드 (신규)
Inspector 패널
⚔ 전투 시뮬레이션
─────────────────────────────
[▶ 시뮬레이션 실행] [📋 이전 결과와 비교]
━━━ 결과 요약 ━━━
✅ 승리 ★★★
남은 라이프: 18/20
총 골드: 3200 | 시뮬 시간: 45.3s
━━━ 웨이브별 상세 ━━━
W1 | 일반 | 적12 | 처치12/돌파0 | 골드180 | 5.0~12.3s
W2 | 일반 | 적15 | 처치13/돌파2 | 골드210 | 14.3~25.1s
W3 | 보스 | 적 3 | 처치 3/돌파0 | 골드450 | 27.1~45.3s
━━━ 타워별 기여도 ━━━
Slot0 Archer Lv2: 데미지 2400 (28%) 처치 8
Slot1 Mage Lv1: 데미지 1800 (21%) 처치 6
Slot3 Barracks : 블록 14회, 데미지 800 (9%) 처치 3
...
━━━ 골드 추이 차트 ━━━
▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
[📝 로그 펼치기]
결과 비교 기능
"이전 결과와 비교" 버튼: 마지막 2회 시뮬 결과를 나란히 비교
비교 항목: 라이프 차이, 골드 차이, 웨이브별 돌파 수 증감
용도: 밸런스 조정 → 시뮬 → 수정 전후 비교 확인
SceneView 표시 (시뮬 후 오버레이)
오버레이
설명
🔴 사망 마커
적이 사망한 경로상 위치에 빨간 X 마커
🟡 돌파 마커
적이 도착점까지 뚫은 경우 경로 끝에 노란 마커 + 수량
🟢 타워 기여도
타워 원 크기가 기여도에 비례하여 변화
🔥 경로 열지도
경로 구간별 "적이 가장 오래 머문 구간" = 두꺼운 주황, 빠르게 지나간 구간 = 얇은 초록
⚠ 사각지대
타워 사거리에 안 걸리는 경로 구간 = 빨간 점선
에러 처리 / 검증
상황
동작
MapConfig 미연결
"MapConfigData를 연결하세요" 경고 + 실행 비활성화
WaveConfig 미연결
"WaveConfig를 연결하세요" 경고 + 실행 비활성화
타워 0개 배치
"타워 없이 시뮬합니다 (모든 적 돌파 예상)" 안내 + 실행 허용
경로 0개
"유효한 경로가 없습니다" 경고 + 실행 비활성화
경로 Waypoint < 2
"PathId=N 의 Waypoint가 부족합니다" 경고
스폰 엔트리의 PathId가 MapConfig에 없음
"PathId=N 이 맵에 존재하지 않습니다" 경고
4. 정밀 시뮬 엔진 개선
4.1 2D 위치 보간
// 경로 Waypoint 리스트 + 이동 거리 → 2D 좌표 계산
Vector3 GetPositionOnPath(List<Vector3> waypoints, float distanceTraveled)
4.2 거리 기반 사거리 판정
// 기존: 경로 진행도 기반 (부정확)
// 개선: 타워 좌표 ↔ 적 좌표 실제 거리
float dist = Vector3.Distance(tower.Position, enemy.CurrentPosition);
if (dist <= tower.Range) { /* 공격 */ }
4.3 타워 타겟팅 규칙
규칙
설명
기본 우선순위
사거리 내에서 경로 진행도가 가장 높은(=도착에 가장 가까운) 적 타겟
다중 경로
경로 무관하게 사거리 내 모든 적을 후보로 포함
타겟 제한
TowerConfig.CanTarget(isFlying) — Flying 적은 Ground 전용 타워에게 무시됨
Artillery AoE
주 타겟 주변 반경(ExplosionRadius) 내 적에게 감소된 데미지
4.4 Barracks 블록 규칙
float dist = Vector3.Distance(rallyPoint, enemy.CurrentPosition);
if (dist <= rallyRange && enemy.CanBeBlocked) { /* 블록 */ }
경로의 모든 구간을 0.5 단위로 샘플링
→ 각 샘플 지점에서 모든 타워까지 거리 계산
→ min(거리) > max(Range) → 사각지대
→ SceneView에 빨간 경로 표시
4.6 적 사망 위치 / 타워별 기여도 추적
// BattleSimResult에 추가
public List<Vector3> EnemyDeathPositions; // 사망 위치
public List<TowerContribution> TowerStats; // 타워별 누적 데미지·처치수
public struct TowerContribution {
public int SlotIndex;
public string TowerName; // 식별 편의
public float TotalDamage;
public int KillCount;
public int BlockCount; // Barracks
}
5. 프리셋 데이터 구조
[CreateAssetMenu(fileName = "TowerPreset", menuName = "Kingdom/Editor/Tower Placement Preset")]
public class TowerPlacementPreset : ScriptableObject
{
public string PresetName;
public int StageId; // 어느 맵 기준인지
public List<SlotPlacement> Placements;
}
[Serializable]
public struct SlotPlacement
{
public int SlotIndex;
public TowerConfig Tower; // null이면 빈 슬롯
public int Level; // 0-indexed
}
저장 경로: Assets/Resources/Kingdom/Configs/TowerPresets/
6. 수정/생성 파일
파일
변경
MapEditorWindow.cs
WaveConfig 슬롯 추가, "타워 배치"/"시뮬" 모드 탭 추가, 결과 패널 통합
BattleSimEngine.cs
GetPositionOnPath(), 거리 기반 판정, 기여도 추적, 사망 위치 기록
BattleSimResult.cs
TowerContribution, EnemyDeathPositions, 사각지대 데이터 추가
BattleSimWindow.cs
삭제 (Phase A step 5에서 제거. 삭제 전 MapEditorWindow 시뮬 탭 완성 선행)