리플렉션(Reflection)

김민수·2025년 1월 23일

언리얼 C++

목록 보기
22/32

Unreal Engine의 리플렉션 시스템은 클래스, 변수, 함수를 메타데이터로 등록해서 에디터에서 활용할 수 있는 시스템이다.

1) 리플렉션과 블루프린트

  • 리플렉션 시스템은 블루프린트와 강하게 연결되어 있다.
    • UCLASS, UPROPERTY, UFUNCTION을 통해 정의된 클래스, 변수, 함수는 블루프린트에서 쉽게 접근 및 확장 가능하다.

2) 리플렉션과 직렬화

  • 리플렉션 시스템은 게임 저장/로드 시 데이터 직렬화 및 역직렬화에 필수적이다.
  • UPROPERTY를 통해 정의된 변수는 자동으로 직렬화 대상이 된다.

3) 리플렉션과 성능

  • 리플렉션은 편리하지만, 사용하지 않는 데이터까지 메타데이터로 관리될 경우 메모리 및 성능에 영향을 줄 수 있다. 꼭 필요한 경우에만 리플렉션을 사용해야 한다.

1. #include "클래스이름.generated.h"

  • 클래스의 리플렉션 데이터를 생성하기 위해 반드시 포함되어야 하는 헤더 파일이다.
  • 클래스이름.generated.h는 Unreal Header Tool(UHT)에 의해 자동으로 생성되며, 리플렉션 데이터를 코드에 연결한다.
  • 일반적으로 클래스 헤더 파일의 마지막 #include로 추가해야 한다.
  • 마지막에 위치하지 않으면 빌드 오류가 발생할 수 있다.
#pragma once

#include "CoreMinimal.h"
#include "Class.generated.h" // 리플렉션 데이터 연결


2. UCLASS

  • 클래스가 Unreal Engine 리플렉션 시스템에 등록되도록 지정하는 매크로다.
  • UCLASS 매크로는 클래스 선언 바로 위에 위치하며, 다양한 메타데이터 옵션을 제공한다.
  • 만약 UCLASS()에 옵션이 없다면, 블루프린트에서 상속이 가능(Blueprintable)하고, 변수로 참조가 가능(BlueprintType)한 형태로 등록된다.
UCLASS(Blueprintable, BlueprintType)
class YOURGAME_API AYourClass : public AActor
{
    GENERATED_BODY()

public:
    AYourClass();
};

옵션 이름설명
Abstract이 클래스를 추상 클래스로 지정한다. 인스턴스화할 수 없게 된다.
Blueprintable블루프린트에서 이 클래스를 기반으로 새로운 블루프린트를 생성할 수 있다.
NotBlueprintable블루프린트에서 이 클래스를 기반으로 블루프린트를 생성할 수 없도록 설정한다.
BlueprintType이 클래스를 블루프린트에서 변수 유형으로 사용할 수 있도록 만든다.
NotBlueprintType이 클래스를 블루프린트에서 변수 유형으로 사용할 수 없도록 설정한다.


3. UPROPERTY

  • 클래스의 변수(속성)을 리플렉션 시스템에 등록한다.
  • UPROPERTY는 변수의 접근성을 제어하거나, 에디터 및 블루프린트에서 이 속성을 제어할 수 있도록 설정할 때 사용한다.
  • 옵션이 하나도 없을 때 엔진 리플렉션 시스템에 등록되지만, 에디터나 Blueprint에 노출되지 않는다.
  • 리플렉션에 등록만 되어 있어도 가비지 컬렉션(메모리 관리)과 직렬화(세이브/로드) 같은 엔진 내부 기능이 작동할 수 있다.
UCLASS()
class YOURGAME_API AYourActor : public AActor
{
    GENERATED_BODY()

public:
    // 에디터에서 수정 가능, 블루프린트에서 읽기/쓰기 가능
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Settings")
    float Speed;
    
    // 에디터에서 읽기 전용, 블루프린트에서 읽기 가능
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Settings")
    int32 Health;
};

블루프린트 관련

옵션 이름설명
BlueprintReadOnly블루프린트에서 읽기만 가능하도록 설정한다.
BlueprintReadWrite블루프린트에서 읽기 및 쓰기가 가능하도록 설정한다.
BlueprintAssignable블루프린트에서 델리게이트를 바인딩할 수 있도록 설정한다.
BlueprintCallable함수처럼 호출 가능한 델리게이트를 정의할 때 사용된다.

에디터 관련

옵션 이름설명
EditAnywhere에디터에서 모든 인스턴스에서 수정 가능하도록 설정한다.
EditDefaultsOnly에디터에서 클래스 기본값만 수정 가능하도록 설정한다.
EditInstanceOnly에디터에서 인스턴스에서만 수정 가능하도록 설정한다.
VisibleAnywhere에디터에서 모든 인스턴스에서 읽기만 가능하도록 설정한다.
VisibleDefaultsOnly에디터에서 클래스 기본값만 읽기 가능하도록 설정한다.
VisibleInstanceOnly에디터에서 인스턴스에서만 읽기 가능하도록 설정한다.


4. UFUNCTION

  • 함수(메서드)를 리플렉션 시스템에 등록해서, 블루프린트에서 호출 가능하거나 네트워크에서 RPC(원격 프로시저 호출)로 사용할 수 있도록 만든다.
  • 옵션이 하나도 없다면, UPROPERTY() 와 같이 리플렉션에 등록되긴 하지만, Blueprint에 노출되지 않는다.
UCLASS()
class YOURGAME_API AYourActor : public AActor
{
    GENERATED_BODY()

public:
    // 블루프린트에서 호출 가능
    UFUNCTION(BlueprintCallable, Category = "Gameplay")
    void StartGame();

    // 블루프린트에서 구현 가능
    UFUNCTION(BlueprintImplementableEvent, Category = "Events")
    void OnPlayerDeath();

    // 서버에서만 실행
    UFUNCTION(Server, Reliable, WithValidation)
    void ServerDoSomething();
};

옵션 이름설명
BlueprintCallable블루프린트에서 이 함수를 호출 가능하도록 설정한다.
NotBlueprintCallable블루프린트에서 호출할 수 없도록 설정한다.
BlueprintImplementableEvent함수 선언만 C++에 있고, 블루프린트에서 함수를 구현할 수 있도록 설정한다. 실제 동작은 이벤트 노드처럼 구현된다.
BlueprintNativeEventC++과 블루프린트에서 모두 구현 가능하도록 설정한다.
BlueprintPureGetter 역할만 수행하도록 설정한다. (Exec 핀 없이 반환값만 노출됨)


5. Category 지정자

  • Category에디터블루프린트에서 속성이나 함수를 그룹화하는 데 사용된다.
  • 이를 통해 구성 요소나 변수를 보기 쉽게 정리할 수 있고, 에디터 디테일 패널에서 속성이나 함수를 특정 그룹 아래에 표시할 수 있다.
  • CategoryUPROPERTYUFUNCTION 매크로에 사용된다.
UCLASS()
class YOURGAME_API AMyActor : public AActor
{
    GENERATED_BODY()

public:
    // 에디터에서 "Gameplay" 카테고리로 표시
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay")
    float MovementSpeed;

    // 에디터에서 "Abilities|Offensive" 카테고리로 표시
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Abilities|Offensive")
    int32 AttackPower;

    // 블루프린트에서 "Utilities" 카테고리로 표시
    UFUNCTION(BlueprintCallable, Category = "Utilities")
    void PrintMessage();
};
  • 단일 이름: Category = "Gameplay"
  • 중첩 구조: Category = "Abilities|Offensive"
    • 중첩 구조를 사용하면 "Abilities" 아래 "Offensive"라는 하위 그룹으로 표시된다.


6. Meta 지정자

Meta는 추가적인 동작과 메타데이터를 설정하기 위해 사용된다.

  • 기본 형식: meta = (key1 = value1, key2 = value2, ...)
  • 적용 위치: UCLASS, UPROPERTY, UFUNCTION

(1) UCLASS에서 사용

Meta는 클래스에 사용자 정의 메타데이터를 추가하거나 특정 동작을 제어할 때 사용된다.

키워드설명
BlueprintSpawnableComponent블루프린트에서 이 컴포넌트를 스폰할 수 있도록 허용한다.
ShortTooltip에디터에서 툴팁으로 간략한 설명을 제공한다.
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent, ShortTooltip = "This is a custom class"))
class YOURGAME_API UMyComponent : public UActorComponent
{
    GENERATED_BODY()
};

(2) UPROPERTY에서 사용

Meta는 변수(속성)에 대한 추가적인 제약 조건이나 정보를 설정하는 데 사용된다.

키워드설명
ClampMin/ClampMax숫자형 속성의 최소/최대 값을 설정한다.
EditCondition다른 속성의 값에 따라 속성을 활성화/비활성화한다.
DisplayName속성이 에디터에서 표시되는 이름을 설정한다.
ToolTip에디터에서 속성에 대한 설명 툴팁을 제공한다.
HideAlphaChannel컬러 속성에서 알파 채널을 숨긴다.
InlineEditConditionToggleEditCondition과 함께 사용하며, Boolean 값을 인라인으로 수정할 수 있도록 설정한다.
MultiLine문자열 속성을 다중 줄 입력 필드로 표시한다.
PasswordField문자열 속성을 비밀번호 입력 필드처럼 표시한다.
UCLASS()
class YOURGAME_API AMyActor : public AActor
{
    GENERATED_BODY()

public:
    // 속성에 최소값과 최대값 설정
    UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = "0.0", ClampMax = "100.0"))
    float Health;

    // 속성 툴팁과 사용자 지정 이름 설정
    UPROPERTY(EditAnywhere, meta = (DisplayName = "Player Speed", ToolTip = "The movement speed of the player"))
    float MovementSpeed;

    // 조건부 활성화 설정
    UPROPERTY(EditAnywhere, meta = (EditCondition = "bCanTakeDamage"))
    float DamageMultiplier;

    // 활성화 조건 토글
    UPROPERTY(EditAnywhere, meta = (InlineEditConditionToggle))
    bool bCanTakeDamage;
};

(3) UFUNCTION에서 사용

Meta는 함수의 추가적인 동작을 지정하거나 에디터/블루프린트에서 표시되는 정보를 제어할 때 사용된다.

키워드설명
DisplayName함수가 블루프린트에서 표시될 이름을 설정한다.
ToolTip함수에 대한 설명 툴팁을 제공한다.
CompactNodeTitle블루프린트 그래프 노드에서 간결한 제목을 표시한다.
Keywords함수의 검색 키워드를 추가한다.
CategoryOverride블루프린트 노드의 카테고리를 재정의한다.
UCLASS()
class YOURGAME_API AMyActor : public AActor
{
    GENERATED_BODY()

public:
    // 함수 이름과 툴팁 설정
    UFUNCTION(BlueprintCallable, Category = "Utilities", meta = (DisplayName = "Print Message", ToolTip = "Prints a message to the log"))
    void PrintMessage();

    // 간단한 노드 제목과 키워드 추가
    UFUNCTION(BlueprintCallable, Category = "Math", meta = (CompactNodeTitle = "Add", Keywords = "Sum,Plus,Addition"))
    int32 AddNumbers(int32 A, int32 B);

    // 카테고리 재정의
    UFUNCTION(BlueprintCallable, meta = (CategoryOverride = "Custom|Utilities"))
    void CustomFunction();
};
profile
안녕하세요

0개의 댓글