본문 바로가기
개발일지/Unreal&C++

[Unreal] 오브젝트 그리고 CDO(Class Default Object), generated.h, GENERATED_BODY

by 쫌눈 2025. 4. 1.
728x90
반응형

언리얼 오브젝트의 베이스 클래스는 UObject.

UClass매크로는 UObject에서 파생된 클래스에 태그를 지정하여 UObject처리 시스템이 인식하도록 할 수 있다.

 

각 UClass는 CDO라는 하나의 오브젝트를 유지한다. 기본적으로 클래스 생성자에 의해 생성되고, 이후에는 수정되지 않는 디폴트 템플릿 오브젝트이다.

UClass와 CDO는 보통 읽기 전용이지만 주어진 오브젝트 인스턴스에 대해 GetClass()함수를 통해 엑세스 할 수 있다.

UClass* RuntimeClass = GetClass();
RuntimeClass->GetDefaultObject<클래스명>();

 

UObject는 모든타입의 함수 혹은 멤버 변수를 가질 수 있다. 언리얼이 이런 변수나 함수를 인식하고 조작하려면 특수 매크로로 표시하고 특정 타입 표준을 준수해야 한다.
UPROPERTY()
UFUNCTION()

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Person.generated.h"

/**
 * 
 */
UCLASS()
class OBJECTREFLECTION_API UPerson : public UObject
{
	GENERATED_BODY()
	
public:
	UPerson();

	UFUNCTION()
	virtual void DoLesson();

	//Getter/Setter
	const FString& GetName() const;
	void SetName(const FString& InName);

protected:
	UPROPERTY()
	FString Name;

	UPROPERTY()
	int32 Year;
};

 

UObject는 엔진 시작 시 초기화 되며, 엔진은 디폴트 생성자를 호출한다. 디폴트 생성자가 없으면 UObject가 컴파일 되지 않는다.

이렇게 되면 생성자가 엔진 시작 시에만 호출될거라 생각하지만 아래의 표를 참고하면 다르다.

상황 생성자 호출 여부 특징
엔진 실행 시(CDO 생성) 호출 클래스의 기본 값 설정, 월드정보 접근 불가
런타임 동적 객체 생성 호출 CDO를 기반으로 초기화. 월드 정보 접근 가능.

엔진 실행시에는 CDO만 생성된다고 생각하면 된다.

UObject생성자는 가벼워야 하고, 디폴트값과 서브 오브젝트를 구성하는데에만 사용해야 하며, 생성 시 다른 함수 기능을 호출해서는 안된다.

액터, 액터 컴포넌트의 경우 초기화 함수를 BeginPlay() 메서드에 넣어 사용할 수 있다.

UObject는 런타임에 NewObject를 사용하거나 생성자의 경우 CreateDefaultSubobject를 사용하여 생성해야 합니다.

Uobject 를 통해 제공되는 함수 기능

  • 가비지 컬렉션
  • 레퍼런스 업데이트
  • 리플렉션
  • 직렬화
  • 디폴트 프로퍼티 변경사항의 자동 업데이트
  • 자동 프로퍼티 초기화
  • 자동 에디터 통합
  • 런타임에 사용 가능한 타입 정보
  • 네트워크 리플리케이션

UHT(Unreal Header Tool)

UObject파생타입이 제공하는 기능을 활용하려면 해당 타입에 대한 헤더파일에 전처리 단계를 실행하여 필요한 정보를 대조해야 하는데 이 전처리 단계를 UHT에서 수행한다.

 

헤더타입 포맷

오브젝트 타입으로 생성한 기본 헤더 파일은 아래와 같다.

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "MyObject.generated.h"

/**
 * 
 */
UCLASS()
class UNREALSAMPLEPROJECT_API UMyObject : public UObject
{
	GENERATED_BODY()
};

언리얼 관련부분은 아래와 같다

#include "MyObject.generated.h"

이 줄은 마지막 #include 지시문이 되어야 한다.

그 이유는 컴파일러가 클래스의 전체 정의를 인식하고 매크로 확장을 올바르게 처리하기 위해서이다.

언리얼 엔진에서의 UCLASS, USTRUCT, UENUM등의 매크로와 관련된 코드가 .generated.h파일에 포함되며, 이 파일은 해당 클래스의 메타데이터와 런타임 정보를 생성하는데 필수적이다.

만약 .generated.h아래에 다른 헤더 파일을 포함하면, 해당 헤더 파일이 .generated.h에서 참조하는 클래스의 정의가 완료되지 않은 상태가 되어 컴파일 오류가 발생한다.
컴파일러는 코드를 위에서 아래로 읽기 때문이다.

.generated.h파일을 살펴보면 (프로젝트 주소\Intermediate\Build\Win64\UnrealEditor\Inc\프로젝트이름\UHT\ 에 있다.) 클래스의 메타데이터와 관련된 코드가 포함되어 있으며, 이를 통해 리플렉션 시스템이 작동한다.

UCLASS()

UCLASS매크로는 언리얼 엔진에 UMyObject가 표시되도록 한다.

GENERATED_BODY()

GENERATED_BODY매크로는 실행인자를 사용하지 않지만 핵심 매크로로, 컴파일시 자동으로 생성되는 코드블록을 삽입하는 역할을 한다. 모든 UCLASS, USTRUCT에 필수적으로 존재해야 한다.
사용하지 않으면 리플렉션 및 블루프린트 기능을 사용할 수 없으며, 에디터와의 상호작용이 불가능하다.
주 역할은 아래와 같다.

  • 리플렉션시스템 지원
    • 클래스와 관련된 메타데이터를 생성해, 런타임에 클래스, 변수, 함수에 동적으로 접근할 수 있도록 지원한다.
  • 직렬화 지원
    • 객체데이터를 저장하거나 로드할 때 필요한 직렬화 코드를 자동으로 생성하여 데이터 저장, 로드 및 네트워크 전송에 도움을 준다.
  • 블루프린트 통합
    • c++로 작성된 클래스를 블루프린트에서 사용할 수 있도록 연결한다.
    • UPROPERTY() UFUNCTION()으로 정의된 변수나 함수가 블루프린트에서 노출된다.
  • 클래스 메타데이터 등록
    • 클래스 선언 시 메타데이터를 등록하여 언리얼 엔진 에디터와 런타임에서 해당 클래스를 인식하고 사용할 수 있게 만든다.
  • 코드 자동생성
    • 내부적으로 접근자 함수, 초기화코드등 다양한 부가 코드를 자동으로 삽입한다.

C++표준에는 C#과 다르게 리플렉션 시스템과 직렬화 기능이 없기 때문에 이를 자동으로 지원하는 매크로이다.(헤더와 cpp파일 모두에 필요한 코드를 생성한다.)

 

 

출처

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/objects-in-unreal-engine

728x90
반응형