내일배움캠프-언리얼

TIL - 92

이시보 2026. 6. 17. 22:46

다중 Row 드랍 & 인벤토리 직접 지급

개요

적 사망 시 여러 드랍 Row를 각각 확률 굴림하여, 마지막으로 공격한 플레이어의 인벤토리로 직접 지급한다. (아이템 액터 스폰 없음)

주요 변경

1. 데이터 구조 — RetrieveDataTableTypes.h

  • FEnemyDropRow: ItemTag(FGameplayTag)ItemId(FName) + ItemCategoryTag(FGameplayTag) (인벤토리 키와 일치)
  • FMonsterDataRow: DropRow(FName)DropRows(TArray<FName>)

2. 드랍 처리 — DropComponent.h/.cpp

  • Initialize(UDataTable*, const TArray<FName>&) — 배열 수신
  • ProcessDrop(): 서버 권한 확인 → 마지막 공격자 폰의 InventoryComponent 확보 → DropRows 각 행을 DropChance로 독립 굴림 → AddItem(ItemId, ItemCategoryTag, Quantity)

3. 적용 지점 — RetrieveEnemyCharacter.cpp

  • InitializeComponents()에서 DropRows.Num() > 0일 때 배열 전달
  • ProcessDrop() 호출은 BP_EnemyBase(사망 시)에서 단일 호출

4. 버그 수정 — CombatAttributeSet.cpp (마지막 공격자 null 문제)

  • 증상: 플레이어가 죽여도 LastDamageInstigator가 null → 드랍 대상(인벤토리) 못 찾음. MonsterDied.Killer도 계속 null이던 잠재 버그.
  • 원인: 데미지가 IncomingDamage 메타 어트리뷰트 → SetHealth()로 적용됨. 이로 인한 Health 변경은 GE 직접 수정이 아니라서 HandleHealthChangedChangeData.GEModData가 null → instigator 세팅 누락. (NotifyDamageContext는 정의만 있고 호출처 없음)
  • 수정: PostGameplayEffectExecute에서 SetHealth() 직전에 EffectContext의 instigator/causer를 HealthComponent->NotifyDamageContext()로 전달.
  • 효과: 근접·원거리·버스트·화상(DoT) 등 모든 데미지 경로에서 마지막 공격자 확정. Killer 잠재 버그도 함께 해결.

미적용 / 참고

  • 보스: RetrieveBossCharacter::HandleDeathStarted는 상위 RetrieveEnemyCharacter를 건너뛰므로 이 드랍 경로를 타지 않음. 보스도 동일 드랍이 필요하면 별도 배선 필요.
  • PlayerState fallback(DropComponent의 폰 해석 보강)은 instigator가 폰으로 확정되어 불필요 → 미적용.

'내일배움캠프-언리얼' 카테고리의 다른 글

TIL - 94  (0) 2026.06.26
TIL - 93  (0) 2026.06.23
TIL - 91  (0) 2026.06.16
TIL - 90  (0) 2026.06.15
TIL - 89  (0) 2026.06.11