티스토리 뷰

🟩 학습 목표

  • 인벤토리 슬롯 데이터에 데이터 테이블 Key 값을 연동하여 런타임 동적 에셋 복원 및 데이터 주도형 아키텍처를 수립한다.
  • FDataTableRowHandle 및 리플렉션 한정자를 활용하여 레벨 디자이너의 휴먼 에러를 원천 차단하는 방어적 C++ 클래스를 설계한다.
  • OnConstruction 라이프사이클 함수를 오버라이드하여 에디터 뷰포트 내 실시간 위지윅(WYSIWYG) 데이터 동기화 시스템을 구현한다.

🟧 1. Data-Driven 인벤토리 아키텍처 개편

🟦 추상 데이터 기반 에셋 복원의 한계점 분석

기존 시스템은 FGameplayTag만을 기반으로 아이템의 카테고리를 분류하였다. 이로 인해 아이템을 필드에 재드롭(Server_DropItem)하는 시점에 해당 아이템이 본래 소유하고 있던 고유 스태틱 메쉬(예: 특정 장비의 고유 외형)가 무엇인지 역산해내지 못하고 기본 베이스 껍데기로만 스폰되는 아키텍처적 한계가 존재하였다.

🟦 ItemID 연동을 통한 동적 메쉬 스폰 메커니즘

인벤토리 최소 단위 구조체인 FInventorySlot이 데이터 테이블의 고유 식별자인 ItemID(Row Name)를 직접 기억하도록 데이터 구조를 개편하였다.

아이템 버리기 함수(Server_DropItem_Implementation)가 호출되면, 슬롯에 저장되어 있던 ItemID를 Key값으로 삼아 DT_ItemData 테이블을 탐색(Lookup)한다. 이후 추출된 행 데이터 내부의 스태틱 메쉬 레퍼런스를 기본 마네킹 액터인 NCItemActor에게 동적으로 주입하여 원본 외형을 완벽하게 복원 및 스폰하도록 로직을 고도화하였다.


🟧 2. 휴먼 에러 방지를 위한 C++ 변수 및 제약 조건 설계

🟦 FDataTableRowHandle을 활용한 데이터 무결성 확보

레벨 디자이너나 기획자가 월드 뷰포트에 아이템 액터를 배치하고 고유 식별자를 문자열(FName, FString) 형태로 직접 타이핑하게 할 경우, 마침표 누락이나 대소문자 오타 등으로 인해 데이터베이스 조회 연산이 실패하는 휴먼 에러가 필연적으로 발생한다.

이를 방지하기 위해 C++ 헤더에 데이터 테이블과 행을 명시적으로 결합하는 FDataTableRowHandle 구조체를 도입하였다.

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item Setting")
FDataTableRowHandle ItemDataHandle;

이 구조체를 선언하면 언리얼 에디터 디테일 패널상에 텍스트 입력창 대신 등록된 데이터 테이블의 모든 Row Name을 직관적으로 선택할 수 있는 '드롭다운 컴보 박스' 목록이 생성되므로 데이터 입력 무결성을 원천 확보할 수 있다.

🟦 VisibleAnywhere를 통한 데이터 변조 방지 (Read-Only)

ItemID나 ItemTypeTag와 같이 데이터 테이블 룩업 완료 후 런타임에 결정되는 핵심 원본 변수들을 사용자가 에디터에서 임의로 수정하여 싱크가 깨지는 현상을 방지해야 한다. 이를 위해 해당 속성들을 읽기 전용으로 제약하는 VisibleAnywhere 매크로를 적용하여 사용자는 눈으로 데이터 검증만 수행하고 직접적인 값 수정은 불가능하도록 방어 코드를 설계하였다.


🟧 3. OnConstruction 오버라이드를 통한 위지윅(WYSIWYG) 환경 구축

🟦 에디터 타임 빌드 시퀀스의 필요성

기존의 BeginPlay() 기반 에셋 할당 로직은 시뮬레이션 버튼(Play)을 누르기 전까지는 월드에 배치된 아이템 액터가 실제 도끼인지, 회복 포션인지 뷰포트상에서 외형적으로 확인할 수 없어 레벨 디자인의 직관성을 저해하는 요소였다.

🟦 실시간 뷰포트 동기화 구현

액터가 월드에 배치되거나 디테일 패널의 컴포넌트 변수 수치가 변경될 때 에디터 타임에서 즉시 트리거되는 라이프사이클 함수인 OnConstruction을 오버라이드하였다.

// NCItemActor.h 선언부
virtual void OnConstruction(const FTransform& Transform) override;

// NCItemActor.cpp 구현부
void ANCItemActor::OnConstruction(const FTransform& Transform)
{
    Super::OnConstruction(Transform);

    if (ItemDataHandle.DataTable && !ItemDataHandle.RowName.IsNone())
    {
        // 에디터 타임에서 드롭다운 수정을 감지하여 즉시 테이블 데이터 파싱
        FItemData* RowData = ItemDataHandle.DataTable->FindRow<FItemData>(ItemDataHandle.RowName, TEXT("OnConstructionFetch"));
        if (RowData && MeshComponent)
        {
            // 플레이 버튼을 누르지 않아도 뷰포트에 실시간 메쉬 변경 반영
            MeshComponent->SetStaticMesh(RowData->ItemStaticMesh);
        }
    }
}

기획자가 디테일 패널에서 아이템 ID를 클릭하는 순간, 백엔드에서 데이터 테이블을 즉각 서치하여 SetStaticMesh를 구동하므로 레벨 디자이너가 인게임 결과를 실시간으로 예측하며 배치할 수 있는 고효율 작업 환경을 완성하였다.


🟧 핵심 요약

  • 슬롯 구조체가 태그를 넘어 테이블 고유 Key인 ItemID를 추적하도록 개편하여 동적 외형 복원 파이프라인을 구축하였다.
  • FDataTableRowHandle 구조체를 연동하여 에디터 내 데이터 입력을 드롭다운 방식으로 규격화하고 오타 버그를 원천 배제하였다.
  • VisibleAnywhere 지정을 통해 기획 데이터의 수동 변조 가능성을 차단하고 시스템 내부 데이터의 안전성을 확보하였다.
  • OnConstruction 함수 캐싱을 활용해 에디터 런타임 이전에 메쉬 데이터를 즉각 동기화하는 위지윅 레벨 디자인 아키텍처를 완수하였다.