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++에 있고, 블루프린트에서 함수를 구현할 수 있도록 설정한다. 실제 동작은 이벤트 노드처럼 구현된다. |
| BlueprintNativeEvent | C++과 블루프린트에서 모두 구현 가능하도록 설정한다. |
| BlueprintPure | Getter 역할만 수행하도록 설정한다. (Exec 핀 없이 반환값만 노출됨) |
5. Category 지정자
Category는 에디터와 블루프린트에서 속성이나 함수를 그룹화하는 데 사용된다.
- 이를 통해 구성 요소나 변수를 보기 쉽게 정리할 수 있고, 에디터 디테일 패널에서 속성이나 함수를 특정 그룹 아래에 표시할 수 있다.
Category는 UPROPERTY와 UFUNCTION 매크로에 사용된다.
UCLASS()
class YOURGAME_API AMyActor : public AActor
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay")
float MovementSpeed;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Abilities|Offensive")
int32 AttackPower;
UFUNCTION(BlueprintCallable, Category = "Utilities")
void PrintMessage();
};
- 단일 이름:
Category = "Gameplay"
- 중첩 구조:
Category = "Abilities|Offensive"
- 중첩 구조를 사용하면 "Abilities" 아래 "Offensive"라는 하위 그룹으로 표시된다.
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 | 컬러 속성에서 알파 채널을 숨긴다. |
| InlineEditConditionToggle | EditCondition과 함께 사용하며, 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();
};