본문으로 건너뛰기

안동민 개발노트

본문 시작

사용자 정의 데이터 인터페이스

C++ 데이터 인터페이스의 클래스·함수·GPU 지원 구조를 이해하고 게임 고유 데이터를 나이아가라 입력으로 노출합니다.

앞서 우리는 나이아가라 시스템이 스태틱 메시, 스켈레탈 메시, 스플라인 등 언리얼 엔진의 기존 데이터를 활용할 수 있도록 돕는 데이터 인터페이스의 기본 개념과 활용법을 살펴보았습니다.

이러한 기본 데이터 인터페이스만으로도 다양한 시각 효과를 만들 수 있지만, 때로는 게임의 특정 로직이나 외부 라이브러리에서 오는 고유한 데이터를 나이아가라 시스템에서 사용하고 싶을 때가 있습니다.

이럴 때 필요한 것이 바로 사용자 정의 데이터 인터페이스(Custom Data Interface)입니다.

사용자 정의 데이터 인터페이스는 나이아가라를 외부 데이터와 연결하는 확장 지점입니다.

C++로 필요한 입력을 노출하면 시스템이 게임 상태나 별도 데이터 소스를 직접 참조할 수 있습니다.

C++ 데이터 인터페이스

기본 데이터 인터페이스가 다루지 못하는 게임 로직, 외부 시뮬레이션, 파일 데이터를 파티클 시스템에 연결합니다.

  1. 데이터 원천

    AI 상태, 날씨 시스템, 외부 물리 계산, CSV/JSON처럼 프로젝트 고유 데이터를 준비합니다. source

  2. C++ 인터페이스

    `UNiagaraDataInterface`를 상속해 읽기/쓰기 함수와 프록시 처리를 구현합니다. backend

  3. 나이아가라 사용

    에디터에서 모듈로 추가하고 출력 핀을 파티클 속성에 연결해 효과를 제어합니다. module


사용자 정의 데이터 인터페이스란?

사용자 정의 데이터 인터페이스는 개발자가 C++ 코드로 직접 구현하여, 나이아가라 시스템이 기본적으로 지원하지 않는 형태의 데이터를 읽거나 쓰도록 확장하는 기능입니다.

이는 마치 나이아가라에 새로운 감각 기관을 추가하여, 게임 세계의 더 복잡하고 특수한 정보를 인식하고 반응할 수 있게 만드는 것과 같습니다.

예를 들어, 다음과 같은 시나리오에서 사용자 정의 데이터 인터페이스가 필요할 수 있습니다.

  • 외부 물리 시뮬레이션 데이터: 게임 내에 커스텀 물리 엔진이나 유체 시뮬레이션이 존재하고, 그 결과 데이터를 나이아가라 파티클에 적용하고 싶을 때.
  • 특정 AI 행동 데이터: AI 캐릭터의 현재 의사결정이나 심리 상태에 따라 파티클 효과를 변화시키고 싶을 때.
  • 게임 특정 상태 데이터: 게임의 고유한 시스템(예: 날씨 시스템, 자원 시스템)에서 오는 복잡한 수치 데이터를 파티클에 반영하고 싶을 때.
  • 파일에서 데이터 읽기: CSV, JSON 등 특정 파일 형식으로 저장된 데이터를 파티클에 적용하고 싶을 때.

사용자 정의 데이터 인터페이스를 구현하려면 기본적인 C++ 프로그래밍 지식과 언리얼 엔진의 모듈 및 클래스 생성에 대한 이해가 필요합니다.

이는 나이아가라의 가장 고급 기능 중 하나이므로, 앞서 배운 기본 개념들을 충분히 숙달한 후에 시도하는 것이 좋습니다.


사용자 정의 데이터 인터페이스의 작동 원리 (개념적 설명)

사용자 정의 데이터 인터페이스는 크게 두 가지 영역에서 작동합니다.

C++ 백엔드 구현
  • UNiagaraDataInterface를 상속받는 C++ 클래스를 생성합니다. 이 클래스에서 나이아가라 시스템이 외부 데이터를 어떻게 읽고(Get), 쓸지(Set)에 대한 로직을 정의합니다.
  • 데이터 인터페이스가 노출할 함수나 변수(예: GetMyCustomValue(), SetMyCustomState())를 정의하고, 이들을 나이아가라 스크립트에서 호출할 수 있도록 등록합니다.
  • 필요에 따라 복잡한 데이터 구조를 처리하거나, 외부 라이브러리와 연동하는 코드를 작성합니다.
나이아가라 프론트엔드 사용
  • C++에서 정의한 사용자 정의 데이터 인터페이스는 나이아가라 에디터에서 일반적인 데이터 인터페이스 모듈처럼 추가하고 사용할 수 있습니다.
  • 스크립트 에디터에서 해당 데이터 인터페이스 모듈의 출력 핀을 파티클 속성에 연결하거나, 입력 핀에 다른 파티클 데이터를 연결하여 파티클의 동작을 제어합니다.

아래 다이어그램은 사용자 정의 데이터 인터페이스에서 C++ 구현, 나이아가라 노드, 시뮬레이션 스레드가 어떤 계약으로 나뉘는지 정리한 것입니다.

C++ 확장 책임 분리

사용자 정의 데이터 인터페이스는 외부 데이터를 가져오는 C++ 코드, 나이아가라에서 호출할 함수, 시뮬레이션 스레드용 프록시가 함께 맞물립니다.

  1. C++ 클래스
    데이터의 소유와 노출 규칙

    C++ 클래스 UNiagaraDataInterface를 상속합니다. UPROPERTY로 에디터 값을 노출합니다. 함수 이름과 타입 계약을 등록합니다.

  2. Niagara 노드
    아티스트가 쓰는 호출 표면

    Niagara 노드 스크립트 에디터에서는 C++ 내부 구조보다 어떤 값을 읽고 어떤 파티클 속성에 연결할지만 보이게 설계합니다.

  3. Proxy
    시뮬레이션 스레드 안전성

    Proxy 프레임별 읽기 데이터를 복사해 둡니다. 게임 스레드 객체에 직접 의존하지 않습니다. GPU/CPU 실행 경로를 구분합니다.


사용자 정의 데이터 인터페이스 구현 단계 (개요)

Custom Data Interface는 외부 데이터 접근 계약을 직접 만든다

기본 DI로 해결되지 않는 요구만 C++ 인터페이스로 열고, 함수와 CPU/GPU 실행 경로를 작게 유지한다.

단계정해야 할 것통과 기준위험
ClassUNiagaraDataInterface 파생 클래스소유 데이터와 책임이 작음범용 유틸 클래스로 커짐
Functions그래프에 노출할 함수와 타입필요한 호출만 명명API가 많아 사용 실수 증가
CPU VMCPU 시뮬레이션 호출 경로프리뷰와 PIE에서 같은 값CPU에서만 동작
GPU PathHLSL과 버퍼 업로드GPU 시뮬레이션도 값 일치업로드 주기와 비용 누락
Tests빈 값, 비활성화, 경계값실패 상태가 예측 가능데이터 없음이 조용히 0으로 보임

사용자 정의 데이터 인터페이스를 만들고 사용하는 일반적인 단계를 간략히 설명합니다. (실제 코딩은 별도의 심화 학습이 필요합니다.)

C++ 프로젝트 설정: 언리얼 엔진 프로젝트가 C++ 프로젝트인지 확인하고, 필요한 경우 새 C++ 클래스를 추가하여 프로젝트를 C++ 프로젝트로 변환합니다.

새 데이터 인터페이스 클래스 생성
  • 언리얼 에디터에서 파일(File) > 새 C++ 클래스 추가(New C++ Class...)를 선택합니다.
  • 부모 클래스 목록에서 NiagaraDataInterface를 검색하여 선택합니다.
  • 클래스 이름(예: MyCustomDataInterface)을 지정하고 클래스를 생성합니다.
데이터 인터페이스 로직 구현
  • 생성된 .h (헤더) 파일과 .cpp (소스) 파일에 데이터 인터페이스의 로직을 작성합니다.
  • 헤더 파일 (.h)
    • 데이터 인터페이스가 노출할 속성(variables)을 UPROPERTY로 선언합니다. 이 속성들은 나이아가라 에디터의 디테일 패널에 노출됩니다.
    • 나이아가라 스크립트에서 호출할 함수를 UFUNCTION(CallInNiagaraScript) 매크로와 함께 선언합니다.
    • FNiagaraDataInterfaceProxy 구조체를 정의하여 시뮬레이션 스레드에서 데이터를 처리할 로직을 구현합니다.
  • 소스 파일 (.cpp)
    • 헤더 파일에 선언한 함수와 속성들에 대한 실제 구현 코드를 작성합니다.
    • 데이터를 읽고 쓰는 방식을 정의하고, 필요한 경우 외부 시스템과 통신합니다.
    • UNiagaraDataInterface::BindInputsUNiagaraDataInterface::Compile과 같은 가상 함수를 오버라이드하여 나이아가라 시스템과의 연결을 설정합니다.

모듈 빌드: 코드를 수정한 후 언리얼 엔진을 닫고 비주얼 스튜디오(Visual Studio)에서 프로젝트를 빌드합니다.

성공적으로 빌드되면 엔진이 새로 만든 데이터 인터페이스를 인식합니다.

나이아가라 시스템에서 사용
  • 나이아가라 에디터를 엽니다.
  • 이미터의 Emitter Update 또는 Particle Update 섹션에 + 버튼을 클릭합니다.
  • 여러분이 만든 사용자 정의 데이터 인터페이스 클래스 이름(예: MyCustomDataInterface)을 검색하여 모듈로 추가합니다.
  • 추가된 모듈을 선택하면 디테일 패널에 C++에서 정의한 속성들이 나타나며, 스크립트 에디터에서는 정의한 함수들을 노드로 사용할 수 있게 됩니다.

사용자 정의 데이터 인터페이스의 장점

  • 궁극적인 유연성: 언리얼 엔진의 모든 데이터와 시스템에 접근하여 나이아가라를 확장할 수 있습니다.
  • 성능 최적화: C++로 직접 구현하므로, 복잡한 계산이나 외부 데이터 처리를 매우 효율적으로 수행할 수 있습니다.
  • 특정 게임 로직 통합: 게임의 고유한 시스템이나 데이터 구조를 파티클 효과에 직접 통합하여, 게임 플레이와 시각 효과 간의 깊은 연동을 가능하게 합니다.

아래 다이어그램은 사용자 정의 데이터 인터페이스를 실제 프로젝트에 넣기 전에 고정해야 할 계약과 검증 지점을 묶은 것입니다.

C++ 확장 데이터 계약

사용자 정의 데이터 인터페이스는 외부 데이터를 읽는 통로이므로 이름, 타입, 갱신 주기, 스레드 경계를 먼저 정해야 안정적으로 쓰입니다.

  1. 게임 데이터

    source 게임 데이터 AI 상태, 날씨, 외부 시뮬레이션처럼 나이아가라 밖의 원천을 정합니다.

  2. UNiagaraDataInterface

    class UNiagaraDataInterface 속성과 함수를 등록해 에디터가 읽을 수 있는 표면을 만듭니다.

  3. 시뮬레이션 프록시

    proxy 시뮬레이션 프록시 런타임 스레드에서 필요한 값만 안전하게 복사하고 계산합니다.

  4. 나이아가라 스크립트

    node 나이아가라 스크립트 노출된 핀을 모듈 입력으로 연결해 파티클 속성에 적용합니다.


사용자 정의 데이터 인터페이스는 게임 로직이나 외부 데이터를 나이아가라 시스템으로 전달할 때 쓰는 확장 지점입니다.

필요한 데이터 형식과 갱신 주기를 명확히 정해야 안정적으로 사용할 수 있습니다.

이것으로 4장 데이터와 매개변수의 모든 절을 마무리하겠습니다.

이제는 나이아가라 시스템의 데이터 흐름과 매개변수 제어에 대한 깊이 있는 이해를 갖게 되셨을 겁니다.

사용자 정의 데이터 인터페이스는 필요성, C++ 구현, 함수 노출, CPU/GPU 실행 경로, 테스트 기준을 통과할 때 도입하는 것이 좋습니다.

사용자 정의 DI는 대체 불가성과 실행 경로를 통과해야 도입한다

기본 Data Interface와 User Parameter로 해결되는 일을 C++ 확장으로 만들면 유지보수 비용이 더 커진다.

게이트검토 질문통과 기준막히면
Need기본 DI나 User Parameter로 해결되지 않는가대체 불가 이유가 문서화됨기본 기능으로 단순화
ClassC++이 소유할 데이터가 명확한가데이터 경계가 작고 이름이 분명함책임을 나누거나 DI 보류
Functions그래프에 열 함수가 최소인가입출력 타입과 이름이 고정됨API를 줄이고 기본값 정리
RuntimeCPU/GPU 실행 경로가 모두 필요한가지원 경로와 비용이 분리됨한 경로만 지원한다고 명시
Test빈 값과 비활성화 상태가 안전한가프리뷰와 플레이 결과가 같음실패값과 로그 기준 추가

사용자 정의 데이터 인터페이스는 구현 비용이 크기 때문에, 만들기 전에 대체 가능성과 검증 기준을 확인합니다.

Custom Data Interface는 마지막 확장 선택이다

기본 인터페이스로 표현하기 어려운 게임 고유 데이터를 C++로 나이아가라에 노출하는 고급 확장이다.

  1. 대체 확인
  2. 계약 고정
  3. 실행 검증
열 구성 · 판단 · 필요 조건 · 구현 범위 · 검증 방법
판단필요 조건구현 범위검증 방법
Need 고유 데이터외부 물리, AI 상태, 날씨, 파일 데이터처럼 기본 함수로 읽을 수 없는 값.User Parameter나 기존 DI 조합으로 충분하면 구현하지 않는다.필요 데이터와 호출 빈도를 먼저 적는다.
C++ Layer 클래스와 함수UNiagaraDataInterface 기반 클래스로 읽기 함수를 정의한다.VM/GPU 지원 범위와 데이터 소유자를 고정한다.데이터 구조 변경 때 깨지는 계약이 작은지 본다.
Expose 스크립트 호출모듈 그래프가 사용할 입력 핀과 함수 시그니처를 노출한다.필요한 입력과 출력만 열어 그래프 사용 실수를 줄인다.함수 이름, 타입, 기본값이 에디터에서 읽히는지 확인한다.
Test 실행 위치CPU/GPU, 에디터 프리뷰, 실제 플레이 값을 따로 본다.실패 시 대체값과 성능 비용을 함께 정한다.GPU 파티클에서 필요한 함수가 실제 지원되는지 확인한다.