Files
2nd/00_Raw/2026-04-26-Skybound_Enemy_Movement_Jitter_Stabilization.md
T

119 lines
4.0 KiB
Markdown

# Skybound Enemy Movement Jitter Stabilization
작성일: 2026-04-26 20:38 KST
## 요청 요약
- 특정 적기들이 서로 낀 것처럼 겹친 채 바들바들 떨린다.
- 적기 이동 로직을 확인하고 원인을 찾아야 한다.
## 확인 결과
문제는 단일 원인이 아니라 세 가지가 겹친 현상으로 판단했다.
### 1. Striker 계열이 플레이어 한 점으로 수렴
`updateStrikerAI`는 각 적기의 편대 위치를 유지하지 않고 `player.x`를 향해 계속 이동했다.
이 때문에 같은 편대로 나온 엘리트/스트라이커들이 시간이 지나면 거의 같은 x 좌표로 모이게 된다.
### 2. 분리 로직이 강한 위치 보정으로 작동
`applyEnemySeparation`은 겹친 적을 매 프레임 직접 밀어냈다.
하지만 직전 AI 로직이 다시 같은 지점으로 끌어당기기 때문에:
- AI가 모음
- separation이 밀어냄
- 다음 프레임에 다시 AI가 모음
이 루프가 반복되며 화면에서는 “끼어서 떠는” 것처럼 보였다.
### 3. 엔티티 풀링에서 내부 속도 잔여값 가능성
적 엔티티는 풀링으로 재사용된다.
그런데 새로 스폰할 때 `vx`, `vy`, 일부 AI 상태값이 명시적으로 초기화되지 않았다.
이전 적이 gravity, knockback, chase 등으로 얻은 내부 속도가 새 적에게 남을 가능성이 있어 이동 불안정성을 키울 수 있었다.
## 적용한 해결 방향
핵심 원칙:
- 적기가 완전히 같은 목표점으로 몰리지 않게 한다.
- 겹침 보정은 강한 튕김이 아니라 작은 안정화 보정으로 한다.
- 풀링된 적기는 스폰 시 내부 이동 상태를 반드시 초기화한다.
## 적용한 변경
### 적 스폰 상태 초기화
수정 파일:
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/EntityManager.ts`
변경:
- `spawnEnemy`에서 아래 값을 기본 초기화하도록 추가했다.
- `vx`
- `vy`
- `hit`
- `hitTimer`
- `stunTimer`
- `targetId`
- `telegraphFrame`
- `telegraphX`
- `telegraphY`
의도:
- 풀링 재사용으로 이전 적의 내부 이동/AI 상태가 새 적에게 이어지는 것을 방지한다.
### Striker 편대 lane 유지
수정 파일:
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/CombatSystem.ts`
변경:
- `updateStrikerAI``player.x`만 추적하지 않고, 스폰 당시 `targetX` 기반의 formation lane을 유지하도록 변경했다.
- 같은 편대에서 나온 적들이 플레이어 중심으로 완전히 겹치지 않고 좌우 간격을 유지한다.
- 근접 압박 이동도 `player.x` 기준이 아니라 `desiredX` 기준으로 변경했다.
의도:
- 엘리트/스트라이커가 “한 점으로 뭉치는” 현상을 줄인다.
- 회피할 수 있는 공격 편대처럼 보이게 한다.
### Enemy separation 안정화
수정 파일:
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/CombatSystem.ts`
변경:
- Elite/MiniBoss의 최소 분리 거리를 늘렸다.
- 동일 좌표 또는 거의 동일 좌표일 때 deterministic escape vector를 적용했다.
- 강한 즉시 위치 보정 대신 작은 보정값을 clamp하여 적용했다.
- 분리 적용 시 `vx`, `vy`를 일부 감쇠하여 AI 이동과 separation이 서로 싸우는 힘을 줄였다.
의도:
- 겹침은 천천히 풀되, 프레임마다 좌우로 튀는 느낌을 줄인다.
- 적기가 낀 듯한 떨림보다 자연스러운 편대 간격 회복으로 보이게 한다.
## 검증
- `npm run build` 성공
- 출력 디렉터리: `dist/47`
## 후속 체크 포인트
- Stage 1에서 엘리트/스트라이커 2기가 겹쳤을 때 떨림이 줄었는지 확인한다.
- 적기가 지나치게 벌어져 난이도가 쉬워지지 않는지 확인한다.
- Striker가 lane을 유지하면서도 플레이어를 압박하는 느낌이 살아있는지 확인한다.
- Chase 계열 일반 적도 같은 문제가 계속 보이면 chase AI에도 lane/flow-field 기반 회피를 추가한다.