UnrealEngine

USTRUCT 정리 - 언리얼 오브젝트 매크로 4

Muji-in 2025. 1. 9. 15:54

사용자 정의 데이터 형식인 구조체도 마킹을 해서 활용할 수 있다. USRUCT를 이용할 경우는 다음과 같은 3가지 용도가 존재한다. 그 중에서 리플렉션 기능은 네트워크 공부할 때 다루고 이번 포스트에서는 다루지 않는다.

  • 에디터와의 통합 : 에디터에서 구조체의 값을 수정할 수 있다.
  • 네트워크 레플리케이션 : 구조체 자체는 레플리케이션 대상이 될 수 없지만 UPROPERTY로 지정한 변수는 레플리케이션이 될 수 있다.
  • 블루프린트 통합 : 블루프린트에서 사용할 수 있게 된다.

USTRUCT 정의

USTRUCT([Specifier, Specifier, ...])
struct FStructName
{
    GENERATED_BODY()
};

UCLASS와 유사하게 정의하고 이름 규칙 상으로 F로 시작해야 한다. 하지만 UPROPERTY만 사용할 수 있고 UFUNCTION은 사용할 수 없다. UPROPERTY를 사용하는 방법 또한 같고 마찮가지로 UObject를 가리킬 경우 UPROPERTY로 마킹을 하면 GC의 도움을 받을 수 있다. 공개 범위의 경우는 UCLASS 내부에서의 허용 범위와 USTRUCT 내부에서의 허용 범위가 모두 일치하면 접근 혹은 수정이 가능하다.

  • UClass EditAnywhere : 모든 곳에서 EditAnywhere 수정 가능, 블루프린트에서만 EditDefaultsOnly 수정 가능, 인스턴스에서만 EditInstanceOnly 수정 가능
  • UClass EditDefaulsOnly : 블루프린트에서 EditAnywhere, EditDefaultsOnly를 수정 가능
  • UClass EditInstanceOnly : 인스턴스에서 EditAnywhere, EditInstanceOnly를 수정 가능
USTRUCT()
struct PLAYGROUND_API FTestStruct
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere)
    int Anywhere = 3;

    UPROPERTY(EditDefaultsOnly)
    int DefaultsOnly = 2;

    UPROPERTY(EditInstanceOnly)
    int InstanceOnly = 1;
};

// ...
    UPROPERTY(EditAnywhere)
    FTestStruct EditAnywhereStuct;

    UPROPERTY(EditDefaultsOnly)
    FTestStruct EditDefaulsOnlyStruct;

    UPROPERTY(EditInstanceOnly)
    FTestStruct EditInstnaceOnlyStruct;
// ...


블루프린트


인스턴스

블루프린트 통합

블루프린트에 통합하기 위해서는 BlueprintType을 정의하면 되고 다음과 같은 효과가 있다.

  • Blueprint에서 클래스의 BlueprintReadOnly, BlueprintReadWrite에 접근 가능
  • Blueprint에서 변수로 선언 가능
  • Make / Break 노드가 자동으로 생성됨

Make / Break

메타를 이용해서 직접 Make, Break를 사용할 수 있지만 기본적으로 Make, Break가 생성되서 활용할 수 있다. Make에서는 ReadWrite 변수가 노출되고 Break에서는 ReadWrite와 Readonly가 노출된다.

USTRUCT(BlueprintType)
struct FBlueprintReadWriteStruct
{
    GENERATED_BODY()

    // Make Node에서 노출
    UPROPERTY(BlueprintReadWrite)
    int BlueprintReadWrite = 1;

    // Make, Break Node에서 노출
    UPROPERTY(BlueprintReadOnly)
    int BlueprintReadOnly = 2;
};

블루프린트 변수로 선언 가능

블루프린트 자체의 변수로도 선언하고 활용할 수 있다.

Class의 Property를 블루프린트에서 접근 가능하도록 설정 가능

UPROPERTY에서 BlueprintReadWrite, BluepirntReadOnly로 설정해서 블루프린트에서 접근 가능하도록 할 수 있다.

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    FBlueprintStruct EditAnywhereBlueprintWriteStruct;

후속 학습

NoExport에 대해서 공부할 필요가 있다. NoExport는 리플렉션 코드를 작성하지 않는 대신 메타 데이터만 추가해주는 태그이다. 리플렉션이 필요 없거나 혹은 USTRUCT로 지정할 수 없을 때 블루프린트에 통합할 때 사용할 수 있다. 대표적으로는 FVector가 템플릿 구조체라서 USTRUCT를 사용할 수 없는데 NoExport를 이용해서 블루프린트에서 사용할 수 있도록 하고 있다. FVecotr의 대략적인 구조는 다음과 같다.

  • MathFwd : 전방 선언, using FVecotr = UE::Math::TVector
  • Vector.h : TVector 선언 및 정의
  • NoExportTypes.h : Blueprint에서의 FVector 정의(NoExport)
  • KismetMathLibray.inl : Blueprint에서의 Make, Break Vector를 정의

여기서 알 수 없는 부분은 블루프린트에서의 FVector가 어떻게 내부의 FVector로 변환되는 과정이다. 블루프린트 내부에서는 TVector를 생성해서 사용하고 있는 것 같은데 그 값이 어떻게 그대로 직렬화 되어서 에디터에서 표기 되는 것을 이해할 수 없다.

참고

  1. 구조체
  2. 코딩 표준
  3. USTRUCT Specifiers Explained (With More on the Way)
  4. Understanding replication atomicity in Unreal Engine
  5. How can FVector pretends as USTRUCT?
  6. Why is FVector not Declared as UStruct(Blueprintable), but we can use it in BPs?