TIL - 회복 아이템 만들기

Kyu_·2026년 7월 7일

33주차

목록 보기
2/4

힐 드롭 시스템 만들기

회복 아이템을 만든다.

재화시스템의 ANSCurrencyReplicationProxy를 미러링해서 회복아이템 전용 프록시 만들기

서버가 특정 플레이어에게만 이 위치에 이런 회복아이템이 생겼다를 알리기 위함

Owner-Only인 이유도 해당 플레이어의 화면에만 픽업아이템이 보이도록


회복 아이템(HP포션) 드랍 시스템 — 작업 기록

몬스터 드랍으로 HP포션(50%/30%/10% 회복)을 추가하는 작업. 재화 드랍 시스템(서버 레지스트리 + Owner-only 프록시 + 클라 로컬 비주얼)을 그대로 미러링해서 구현.

1. 회복 비주얼 데이터를 어디 둘지 — 세 번 갈아엎음

1차 시도: 픽업 BP에 TMap<int32, TSoftObjectPtr<UStaticMesh>> TierMeshMap을 직접 박아둠.

  • 문제: 이 프로젝트 원칙("수치/밸런스는 DataTable 우선")과 안 맞음. 새 포션 추가할 때마다 BP를 열어야 함.

2차 시도: DT_HealVisual(RowStruct=FNSHealVisualRow, Mesh+Scale만) 신규 생성, RowName을 회복 퍼센트 문자열("50"/"30"/"10")로 매핑. 드랍테이블의 범용 Quantity 필드를 회복 퍼센트로 재사용(MinQuantity=MaxQuantity=50/30/10).

  • 문제: Quantity가 원래 "몇 개"를 의미하는 필드인데 회복%로 몰래 재사용해서, 드랍테이블만 보면 그 50이 개수인지 퍼센트인지 알 수 없음. "1로 두면 안 되나?"라는 질문에 답하다가 이 설계의 취약함이 드러남 — Quantity 필드 하나에 "몇 티어가 뽑히는지(Weight)"와 "그 티어가 실제로 몇 %인지(Quantity)"라는 두 가지 역할이 겹쳐 있었음.

3차(최종) 설계: 재화의 CurrencyTag와 동일한 패턴으로 FGameplayTag HealPotionTagFNSRewardDropRow/FNSRewardDropResult에 추가. 드랍테이블은 "어떤 포션인지"만 태그로 식별(Reward.Potion.Heal.Large/Mid/Small — 태그명에 퍼센트를 안 넣음, DT에서 밸런스를 바꿔도 태그명이 거짓말하지 않도록). 회복%·메시·스케일은 DT_HealPotion(RowStruct=FNSHealPotionRow) 한 곳에 통합해서, RowName=태그 전체 이름으로 조회.

  • : 보상 타입마다 자기 식별 필드를 하나씩 갖는 기존 패턴(CurrencyTag/PartDefinition/AugmentPoolTag)에 자연스럽게 얹혔고, "새 포션 추가 = DT 행 하나 + 드랍행 하나, 코드 수정 0"이 됨. 서버(UNSHealDropSubsystem::ApplyHealEffect)와 클라(ANSLocalHealPickup::StartMeshLoad) 둘 다 같은 DT를 태그로 조회하므로 회복%와 비주얼이 항상 같은 소스에서 나옴(불일치 불가능).

2. 풀피 상태 수집 처리

  • 초기 설계: "풀피여도 그냥 소모됨(단순화 우선)"으로 미결 항목으로 남겨둠.
  • 변경 결정: 최대체력 증강이 있는 게임이라 %회복으로 설계했는데, 풀피에서도 소모되면 아이템 낭비가 실사용에서 자주 발생할 문제라 판단해 스킵 로직 추가.
  • 구현: ApplyHealEffectvoidbool로 변경. 맨 앞에서 Health >= MaxHealth면 GE를 적용하지 않고 false 반환. TryCollectfalse를 받으면 CollectedPlayer에 기록하지 않고(소모 안 됨) SendRestoreEvent(DropId)로 그 플레이어 화면의 낙관적 숨김을 되돌림 — 나중에 체력이 줄면 같은 드랍을 다시 시도 가능.
  • 부수 발견: 이 작업을 하다가 재화 시스템(UNSCurrencyDropSubsystem)에는 애초에 SendRestoreEvent를 호출하는 코드가 어디에도 없다는 기존 갭을 발견함. 이번엔 Heal에만 적용, 재화 쪽은 범위 밖으로 남겨둠.

PR 작성

  • 우선 Normal 몬스터 DT에만 추가
    스크린샷 2026-07-07 202903
    회복 Group을 만들고, Heal Potion Tag로 회복 아이템 식별

  • DT_HealPotion에서 확률, 메시, 스케일 조정, RowName은 태그로
    스크린샷 2026-07-07 202926

  • RunConfig에 등록
    스크린샷 2026-07-07 210848

  • BP_RunGameMode에 Heal프록시 등록
    스크린샷 2026-07-07 174859

  • Heal프록시에 DT, 픽업 클래스 등록

스크린샷 2026-07-07 190936 스크린샷 2026-07-07 174730

RPC

클라이언트에서 발생한 이벤트를 서버로 전달하여 서버에서 로직을 실행하려면 Server RPC를 사용해야 한다. UFUNCTION(Server, Reliable, WithValidation) : 즉 통신의 신뢰성 보장을 위한 Reliable, 클라이언트의 요청을 서버가 검증할 수 있도록 WithValidation 지정자를 함께 사용하는것이 적절

UFUNCTION(Server, Reliable)
void Server_SendChatMessage(FString& Message);

컴파일 했을때 결과 : RPC는 비동기 단방향 통신으로 값을 되돌려받기 위한 비상수 참조(Non-const Reference)를 파라미터로 사용할 수 없어 언리얼 헤더 툴(UHT)에러가 발생한다.

언리얼 C++에서 RPC를 통해 TArray와 같은 배열이나 구조체를 인자로 전달할 때는 값 복사에 의한 성능 저하를 막기 위해 const 참조(const &)를 사용하는 것이 가장 효율적

0개의 댓글