UE5 증강 시스템 개편

Kyu_·2026년 6월 1일

28주차

목록 보기
1/3

증강 시스템 개편 작업 요약


변경점 한눈에 보기

#무엇을
1IMC 전환 방식 → C++ 패널 체크로 교체증강창 열려도 이동/스킬 막히지 않게
2증강 대기열(큐) 시스템 추가증강 여러 개 쌓아두고 순서대로 처리
3Tab = 패널 토글, P = 디버그 적재획득 시 자동 오픈 + 수동 열기/닫기
4위젯 구조 개편보유 아이콘 상시 표시 + 카드 영역 분리
5MaxStack 도달 시 카드 후보 제외꽉 찬 증강은 더 이상 안 뜨게
6보유 아이콘 SizeBox 적용텍스처 크기와 무관하게 일정 크기 표시

1. 입력 방식 변경 — IMC 전환 제거

기존 방식 (문제)

증강창이 열리면 IMC_Augment 하나로 교체 → 게임플레이 IMC가 제거되어 이동·스킬이 막힘.

새 방식

게임플레이 IMC는 항상 살아있고, 1/2/3/T 키 입력이 오면 C++에서 패널 열림 여부만 확인:

1/2/3/T 키 누름
  → Input_AugmentAction 호출
      → 패널 열려있음? NO → 그냥 무시 (게임플레이 계속)
      → 패널 열려있음? YES → 카드 선택 / 리롤 처리

에디터에서 해야 할 작업

  • 기존 IMC_Augment에 있던 1/2/3/T 매핑을 게임플레이 IMC로 이동
  • IMC_Augment 에셋 삭제 가능

변경된 파일

  • NSInputBinderComponent.h/.cppEnterAugmentInputMode, ExitAugmentInputMode, CachedInputModeTagsBeforeAugment 삭제. Input_AugmentAction에 패널 체크 한 줄 추가.

2. 증강 대기열(큐) 시스템

기존 방식 (문제)

RequestOffer(PoolTag) 하나로 즉시 추첨·표시. 쌓아두는 개념 없었음.

새 방식

서버에 TArray<FGameplayTag> PoolQueue (FIFO 큐)를 두고, 획득 이벤트마다 큐에 쌓음. 선택하면 하나씩 소비.

엘리트/레벨업/보물상자 → EnqueueOffer(풀태그)
  → 큐에 추가, 카운트++
  → 클라이언트 패널 자동 오픈
  → 아직 표시 중인 카드 없으면 즉시 추첨·표시

카드 선택 → Server_Choose(인덱스)
  → 증강 적용
  → 큐에서 front 제거, 카운트--
  → 큐에 남은 것 있으면 → 다음 카드 자동 표시
  → 큐 비었으면 → 카드 영역만 닫기 (패널은 유지)

핵심 개념: bFrontRolled

한 번 추첨된 카드는 재오픈해도 같은 카드가 표시됨 (무료 리롤 방지). 리롤(T키)을 눌러야만 새로 추첨.

PendingCount 레플리케이션

PendingCount (대기 개수)는 오너 클라이언트에게만 레플리케이션 → UI 뱃지 갱신에 사용.
리슨서버 호스트는 OnRep가 안 불리므로 서버에서 직접 Broadcast.

추가된 함수

함수누가 호출역할
EnqueueOffer(PoolTag)서버 트리거 (레벨업/엘리트 등)큐에 적재 + 자동 오픈
Server_EnqueueOffer클라이언트 트리거 (보물상자)서버에 적재 요청
Server_OpenPanelTab으로 열 때front 오퍼 표시 요청
Server_RerollCard리롤 키(T)강제 재추첨
Server_Choose(Index)카드 키(1/2/3)증강 적용 + 큐 소비

삭제된 함수

  • RequestOffer(PoolTag)EnqueueOffer로 대체
  • Server_RequestOfferServer_EnqueueOffer로 대체

변경된 파일

  • NSAugmentSelectionComponent.h/.cpp

3. Tab 토글 + 디버그 적재

Tab키

ToggleAugmentationPanel() — 패널이 열려있으면 닫고, 닫혀있으면 열기.
열 때: UI 표시 + Server_OpenPanel 호출 (대기 카드 있으면 표시).

O키 (디버그용, 나중에 제거)

Debug_EnqueueAugmentOffer() — Normal 풀 증강 하나를 큐에 적재. 런 데이터가 없으면 자동 로드 후 적재.
실제 게임에서는 엘리트 처치/레벨업 이벤트가 EnqueueOffer를 직접 호출하게 됨.

변경된 파일

  • NSPlayerController.h/.cppOpenAugmentationSelection/OnTestRunDataReady(기존 테스트 코드) 교체

4. 위젯 구조 개편

기존 구조 (문제)

패널 열림 = 카드 표시. 닫힘 = 전부 숨김. 보유 아이콘 없음.

새 구조

[NSAugmentationWidget] — Tab으로 열고 닫는 전체 패널
  ├─ OwnedAugmentWrapBox  ← 패널 열린 동안 항상 표시 (보유 증강 아이콘들)
  ├─ PendingCountText     ← 대기 카운트 뱃지 ("2" 등)
  └─ CardSectionRoot      ← 대기 > 0일 때만 표시
      └─ ChoiceRootCanvas ← 카드 3장

패널 열기/닫기 흐름

Tab 또는 자동 오픈
  → UIManager::OpenAugmentationPanel()
    → HUDWidget::OpenAugmentationPanel()
      → NSAugmentationWidget::OpenPanel()
        → Visible, 보유 아이콘 갱신

카드 선택 완료 or 대기 0개
  → Client_CloseOffer → HandleOfferClosed
    → HideCardSection() (카드만 숨김, 패널은 유지)

Tab으로 닫기
  → UIManager::CloseAugmentationPanel()
    → NSAugmentationWidget::ClosePanel()
      → Collapsed (패널 전체 숨김)

BindWidgetOptional 멤버 (BP에 배치 필요)

C++ 변수명BP 위젯 타입역할
CardSectionRoot아무 컨테이너 (SizeBox 등)카드 영역 표시/숨김 토글
OwnedAugmentWrapBoxWrapBox보유 증강 아이콘들
PendingCountTextCommonText대기 카운트 뱃지

BindWidgetOptional — BP에 없어도 빌드/실행 됨. 없으면 해당 기능만 비활성.

UIManager에 추가된 함수

함수역할
OpenAugmentationPanel()패널 열기 (중복 호출 방지 포함)
CloseAugmentationPanel()패널 닫기
IsAugmentationPanelOpen()패널 열림 여부 반환 (InputBinder 게이팅용)

변경된 파일

  • NSAugmentationWidget.h/.cpp
  • NSHUDWidget.h/.cpp
  • NSUIManagerSubsystem.h/.cpp

5. MaxStack 도달 시 카드 후보 제외

동작

보유 증강의 스택 수 (Inst.Stacks)가 Definition의 MaxStack에 도달하면, 이후 카드 추첨 시 그 증강이 후보에서 제외됨.

기본값

NSAugmentDefinitionMaxStack 기본값 = 5
에디터에서 각 DA(Data Asset) → Meta 카테고리 → MaxStack으로 증강별 조정 가능.

주의: 기존에 만들어진 DA는 저장된 값(기본 1)을 그대로 가지고 있음.
DA 열어서 MaxStack이 1이면 한 번 선택 후 바로 사라지는 게 정상.
에디터에서 직접 5로 바꿔야 함.

변경된 파일

  • NSAugmentDefinition.hMaxStack 기본값 1 → 5
  • NSAugmentSelectionComponent.cppCollectInventoryFilter에 스택 풀 수집, BuildRarityBuckets에 필터 적용

6. 보유 아이콘 SizeBox 적용

기존 (문제)

SetBrushFromTexture만 하면 텍스처 원본 픽셀 크기로 표시 → 아이콘마다 크기 제각각.

새 방식

각 아이콘을 SizeBox로 감싸서 OwnedIconSize(기본 48×48)로 고정.

WrapBox
  └─ SizeBox (48×48 고정)
      └─ Image (텍스처)

에디터에서 WBP_AugmentationWidget → Details → UI → OwnedIconSize로 크기 조정 가능.

변경된 파일

  • NSAugmentationWidget.hOwnedIconSize UPROPERTY 추가, USizeBox forward decl 추가
  • NSAugmentationWidget.cppOnOwnedIconsLoaded에서 SizeBox 동적 생성

7. 코드 최적화 (SelectionComponent)

RollAndPresent 제거

기존에 PresentFront(일반 표시)와 RollAndPresent(리롤용 강제 재추첨) 두 함수가 따로 있었음.
PresentFront(bool bReroll = false) 하나로 통합.

  • bReroll = false (기본): 미추첨이면 추첨, 이미 추첨됐으면 캐시 재전송
  • bReroll = true: 무조건 새로 추첨 (리롤 시 호출)

CurrentOfferRarity 멤버 삭제

쓰기만 하고 읽는 곳이 없던 죽은 상태. 제거.


전체 데이터 흐름 요약

[획득 이벤트 발생] (엘리트 처치 / 레벨업 / P키 디버그)
       ↓
  EnqueueOffer(PoolTag) [서버]
       ↓
  PoolQueue에 추가, PendingCount++
       ↓
  Client_AutoOpenPanel → 패널 UI 열림
       ↓
  PresentFront() → 카드 3장 추첨 → Client_PresentOffer
       ↓
  HandleOfferPresented → 카드 위젯 생성 + 아이콘 비동기 로드
       ↓
  [플레이어가 1/2/3 눌러서 선택]
       ↓
  Input_AugmentAction → 패널 열림? → Server_Choose(Index)
       ↓
  ApplyAugment → 보유 목록에 추가
       ↓
  큐에 남은 것 있으면 → 다음 카드 자동 표시
  큐 비었으면 → 카드 영역 숨김 (패널은 유지, 보유 아이콘만 표시)

증강 시스템

증강이 쌓이는 구조 만들기

  • 기획에서는 큐를 사용해서 증강이 쌓이는 구조를 만들고자 하여서 TQueue를 사용하려고 했었다.
  • TQueue는 근데 이 상황에서 상당히 적합하지 않다는 결론이 내려졌다.

공식문서를 읽어보면 TQueue의 용도는 lock-free linked list기반이라고 되어있는데 말그대로 멀티스레드 환경에서 안정적으로 사용할 수 있다고 한다. 하지만 우리는 게임스레드에서만 호출하므로 별로 필요가 없고, 오히려 크기에 접근을 해야하는데 큐의 특성상 크기를 반환하는 메서드가 없으므로 TArray를 큐처럼 쓰는게 낫지않을까 싶었다.

0개의 댓글