refactor(BT12-Dev): IsFlying 속성 SOT EnemyController 단일화 (PD 지적 2026-05-15)

PD 지적: "enemy 랜덤풀에 플라잉 몬스터를 설정하는게 아니라
개별 몬스터 특성에 플라잉 속성을 부여해야하지 않을까?"

직전 commit 60c2e9b 의 2 위치 분산 (MonsterRandomizer.flyingFlags +
EnemyController hardcoded "M002") 정정. SOT 단일화.

설계:
- EnemyController.flyingControllerNames string[] (Inspector 기본
  { "M002" }) — 개별 몬스터 특성 IsFlying 속성 단일 SOT
- EnemyController.RecheckFlyingFromAnimator() public method 신설
  · Animator.runtimeAnimatorController.name 영역 flyingControllerNames
    list 매칭 → IsFlying=true 자동
  · control.gravityModifier=0·velocity=0·ignoreCollisions=true 일괄
- EnemyController.Awake + Start 영역 RecheckFlyingFromAnimator 호출
- MonsterRandomizer.Awake 영역 controller random 후 위임 호출만

폐기:
- MonsterRandomizer.flyingFlags bool[] (분산 SOT 폐기)
- MonsterRandomizer name fallback "M002" hardcoded (분산 폐기)
- EnemyController.Awake 직접 hardcoded "M002" check (분산 폐기)

확장: 후속 공중 몬스터 추가 (예: 까마귀 M005) 시 PD Inspector
flyingControllerNames 배열에 controller name 추가만 하면 자동 적용.

검증 (Play 모드):
- 총 Enemy 16기 · M002 박쥐 3기 모두 IsFlying=True
- M005 등 비박쥐 IsFlying=False · gravMod=1 (지상 정상)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
깃 관리자 2026-05-15 00:35:47 +09:00
parent 60c2e9bf09
commit 190c96918b
2 changed files with 42 additions and 45 deletions

View File

@ -15,9 +15,13 @@ namespace Platformer.Mechanics
public AudioClip ouch;
// PD 지시 2026-05-15 — 날으는 몬스터 (M002 박쥐 등) 영역 — 중력·cliffCheck·떨어짐 텔레포트 모두 skip.
// MonsterRandomizer.flyingFlags 영역 자동 set 또는 Inspector 직접 토글 가능.
public bool IsFlying = false;
// PD 지시 2026-05-15 — 개별 몬스터 특성 IsFlying 속성 SOT (controller name 매칭)
// Animator.runtimeAnimatorController.name 영역 본 list 영역 영역 영역 IsFlying=true 자동 set.
// 기본값 M002 (박쥐). 추가 공중 몬스터 영역 PD Inspector 영역 영역.
public string[] flyingControllerNames = new[] { "M002" };
// BT12-Dev 2026-05-11 — 밟기 공격 기능 제거 (PD 지시): hitRangeX·hitRangeY·stompMinDy 폐기.
// Enemy는 Player 공격에만 피해를 받으므로 Player ↔ Enemy 충돌 감지 자체 불필요.
@ -105,25 +109,8 @@ namespace Platformer.Mechanics
// Layer 14 (Enemy) ↔ Layer 14 collide X·전역 1회 적용 (Awake 영역 매번 호출 무관·idempotent).
Physics2D.IgnoreLayerCollision(14, 14, true);
// PD 지시 2026-05-15 — Animator.runtimeAnimatorController name 영역 M002 (박쥐) 영역 IsFlying=true 자동
// (MonsterRandomizer 부재·Animator 직접 controller 부착 케이스 보강)
if (!IsFlying)
{
var anim = GetComponent<Animator>();
if (anim != null && anim.runtimeAnimatorController != null
&& anim.runtimeAnimatorController.name.Contains("M002"))
{
IsFlying = true;
}
}
// PD 지시 2026-05-15 — 날으는 몬스터 영역 중력 무효 + collide 무시 (이동 정합)
if (IsFlying && control != null)
{
control.gravityModifier = 0f;
control.velocity = Vector2.zero;
control.ignoreCollisions = true;
}
// PD 지시 2026-05-15 — 개별 몬스터 특성 IsFlying 속성 자동 적용 (controller name 매칭)
RecheckFlyingFromAnimator();
// PD 명시 2026-05-08 — 자동 patrol 시작 위치 저장 (측정·target은 Start 시점)
_startX = transform.position.x;
@ -139,14 +126,8 @@ namespace Platformer.Mechanics
// BT104 — 시작 위치 발판 검증·자동 재배치 (PD가 PD Foreground·빈 영역 배치 시 가까운 발판 영역으로 이동)
void Start()
{
// PD 지시 2026-05-15 — MonsterRandomizer.Awake → EnemyController.IsFlying=true 영역 EnemyController.Awake 이후 set 가능
// Start 영역 IsFlying flag 재적용 (Awake 시점 미반영 케이스 보강).
if (IsFlying && control != null)
{
control.gravityModifier = 0f;
control.velocity = Vector2.zero;
control.ignoreCollisions = true;
}
// PD 지시 2026-05-15 — MonsterRandomizer.Awake → controller 변경 영역 Start 시점 재 check
RecheckFlyingFromAnimator();
// BT109 — Raycast 영역 폐기 (BT104 영역 부정확). Tilemap cell 기반 시작 위치 발판 검증.
_startY = transform.position.y;
@ -160,6 +141,34 @@ namespace Platformer.Mechanics
_isInitialized = true;
}
// PD 지시 2026-05-15 — 개별 몬스터 특성 IsFlying 속성 자동 재적용 (Animator name 매칭)
// MonsterRandomizer.Awake 영역 controller random 후 호출 가능 (public).
public void RecheckFlyingFromAnimator()
{
if (!IsFlying)
{
var anim = GetComponent<Animator>();
if (anim != null && anim.runtimeAnimatorController != null && flyingControllerNames != null)
{
string rcName = anim.runtimeAnimatorController.name;
foreach (var fn in flyingControllerNames)
{
if (!string.IsNullOrEmpty(fn) && rcName.Contains(fn))
{
IsFlying = true;
break;
}
}
}
}
if (IsFlying && control != null)
{
control.gravityModifier = 0f;
control.velocity = Vector2.zero;
control.ignoreCollisions = true;
}
}
// BT96 — 절벽·벽 검출 시 즉시 반대 방향 이동 (transform + body 동시 push·KinematicObject 정합)
void TriggerReverse(float moveDir, float pushDistance)
{

View File

@ -15,30 +15,18 @@ namespace Platformer.Mechanics
[Tooltip("6 AnimatorOverrideController (M001~M006).")]
public AnimatorOverrideController[] overrideControllers;
// PD 지시 2026-05-15 — 날으는 몬스터 영역 (M002 박쥐 등)
// overrideControllers 영역 동일 length·true 영역 EnemyController.IsFlying=true 자동 set
[Tooltip("각 overrideController 영역 IsFlying flag (동일 length). 박쥐 등 공중 몬스터 영역 true.")]
public bool[] flyingFlags;
void Awake()
{
if (overrideControllers == null || overrideControllers.Length == 0) return;
var anim = GetComponent<Animator>();
if (anim == null) return;
int idx = Random.Range(0, overrideControllers.Length);
var selected = overrideControllers[idx];
anim.runtimeAnimatorController = selected;
anim.runtimeAnimatorController = overrideControllers[idx];
// PD 지시 2026-05-15 — 박쥐 선택 시 EnemyController.IsFlying=true 자동 set
// flyingFlags Inspector 설정 우선 · 미설정 시 controller name fallback (M002 = 박쥐)
bool isFlying = false;
if (flyingFlags != null && idx < flyingFlags.Length && flyingFlags[idx]) isFlying = true;
else if (selected != null && selected.name.Contains("M002")) isFlying = true;
if (isFlying)
{
var ec = GetComponent<EnemyController>();
if (ec != null) ec.IsFlying = true;
}
// PD 지시 2026-05-15 — 개별 몬스터 특성 IsFlying 속성은 EnemyController.flyingControllerNames SOT
// controller 변경 직후 재 check 위임 (랜덤풀 영역 IsFlying 결정 X·개별 controller 특성 영역 결정)
var ec = GetComponent<EnemyController>();
if (ec != null) ec.RecheckFlyingFromAnimator();
}
}
}