# 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 기반 회피를 추가한다.