내일배움캠프_Unreal/TIL

내일배움캠프_Unreal/TIL - Day 126 (260601)

하임 2026. 6. 1. 20:57

Heavy Attack 구현 중

1. 효과 분기는 단일 GA가 아니라 다중 GA + 태그 라우팅으로
모드별(Fire/Water/Wind) 효과 카테고리가 완전히 달라(공격/제어/이동) 단일 GA에 거대 switch를 넣으면 유지보수 지옥이 됨. Base(공통) + 자식 3개 구조로 쪼개고, 셋 다 같은 우클릭 InputTag로 부여한 뒤 ActivationRequiredTags(Element.Fire/Water/Wind)로 현재 모드와 일치하는 하나만 통과시키는 자동 분기를 씀. 별도 매니저 없이 태그만으로 라우팅됨.

2. 자원 소모는 "검사"가 아니라 "소모 결과"가 권위가 되어야 함
ConsumeOldestSlot()이 FGameplayTag를 반환(실패 시 Element.None)한다는 점을 활용 → 반환값 자체가 성공/실패 판정. CanActivate에서 검사하고 Activate에서 소모하는 2단계는 그 사이 race condition 위험이 있는데, 소모 호출 한 번으로 검사+소모를 원자적으로 처리해 회피함.

3. ServerInitiated vs LocalPredicted는 자원의 복제 여부로 갈림
게이지 컴포넌트가 비복제·서버 권한이라, LocalPredicted로 두면 클라가 게이지를 못 봐 오예측함. ServerInitiated로 권한을 서버에 일원화(입력 latency를 감수)하는 게 정합성 측면에서 맞다는 판단. "반응성 좋으니 무조건 LocalPredicted"가 정답이 아님을 배움.

4. Attack.Type과 Attack.Property는 직교한 축으로 분리
"강도(Type, 택1)"와 "부가 특성(Property, 조합 가능)"을 한 태그 축에 섞으면 Heavy인데 가드 깸 / Normal인데 가드 깸 같은 조합이 불가능해짐. GuardBreak를 Type에서 떼어 Property로 빼서 "강함 ≠ 가드 깸"을 분리 → 미래 조합 자유 확보.

5. 구현 전 "기획 가정 vs 실제 코드" 사전 점검의 가치
기획서 가정이 실제 코드와 여러 군데 달랐음: 모드 태그가 State.Element.*가 아니라 Element.*, GetSlotCount()은 현재 충전 수가 아니라 최대치(3) 고정 반환(함정), 방어 메서드명·감쇠 배율도 상이. 코드를 먼저 읽지 않았으면 인터페이스가 전부 어긋날 뻔함.

6. 외부 리뷰도 코드/시그니처로 검증 — 할루시네이션 색출
리뷰가 "치명적 버그"로 단정한 2건을 그대로 수용하지 않고 대조: WaitGameplayEvent(..., false, true)의 마지막 인자를 OnlyTriggerOnce로 오독한 것이었고(실제 4번째=OnlyTriggerOnce=false, 5번째=OnlyMatchExact), 엔진 시그니처를 직접 확인해 반증함. "권위 있어 보이는 지적"도 사실관계부터 확인해야 함.