Notice
Recent Posts
Recent Comments
Link
«   2026/06   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

MOONSUN

[UE5] C++을 언리얼 오브젝트 클래스로 만드는 규칙 본문

UE5

[UE5] C++을 언리얼 오브젝트 클래스로 만드는 규칙

MoonSun_v 2026. 3. 26. 19:32

 

어떤 C++ 클래스가 언리얼 오브젝트 클래스가 되려면 다음과 같은 규칙이 필요하다.

 

1. UCLASS / GENERATED_BODY 매크로
2. 클래스 접두사 규칙
3. generated.h 헤더 파일
4. 모듈명_API

 

 

 

1. UCLASS() / GENERATED_BODY() 매크로

  • 클래스 위에 UCLASS()
  • 클래스 내부에 GENERATED_BODY()
UCLASS() 는 해당 클래스가 언리얼의 리플렉션 시스템에 참여하는 클래스라는 것을 표시하고,
GENERATED_BODY() 는 그 클래스에 필요한 내부 코드를 삽입해준다.

 

 

좀 더 자세히 보면, 이 매크로 자체가 직접 모든 기능을 수행하는 것은 아니고,

 

Unreal Header Tool(UHT)가 이 매크로들을 보고 필요한 코드를 생성한 뒤,

그 생성된 코드가 generated.h 를 통해 포함되면서 실제 기능이 연결되는 것. 

 

1. 헤더에 UCLASS(), GENERATED_BODY()를 작성
2. UHT가 헤더를 분석
3. 언리얼이 필요한 부가 코드를 생성
4. .generated.h를 통해 클래스에 포함
5. 그 결과 리플렉션, GC(가비지 컬렉션), 블루프린트 연동 등이 가능해짐
  • * 리플렉션(Reflection)이란? 
    • 프로그램이 실행 중에 “이 클래스가 어떤 타입인지, 어떤 변수와 함수가 있는지”를 알 수 있게 해주는 기능
  • * 가비지 컬렉션(GC) 이란?
    • 더 이상 사용되지 않는 객체의 메모리를 자동으로 정리하는 시스템
    • 일반 C++에서는 개발자가 new와 delete를 직접 관리해야 하지만, 언리얼은 UObject 계열 객체에 대해서 자체 GC 시스템을 사용함 

 

1-1. UPROPERTY 매크로

멤버 변수를 언리얼이 인식할 수 있도록 표시하는 매크로

 

UCLASS는 “클래스 등록”
UPROPERTY는 “변수 등록”

둘 다 언리얼 리플렉션 시스템에 참여시키는 핵심 매크로

 

 

 

 

2. 클래스 접두사 규칙

언리얼 클래스는 이름 앞에 접두사를 붙이는 규칙이 있다.

class UNREALSTUDY_API AMyActor : public AActor
  • A : Actor 클래스 (AActor 상속)
  • U : Actor가 아닌 일반 클래스 UObject
  • F : 구조체 (Struct)
  • I : 인터페이스

 

 

 

3. generated.h 헤더 파일

#include "MyActor.generated.h"

 

이 헤더는 반드시 include의 마지막에 와야함 !!

 

이유는 generated.h가 UHT가 생성한 코드를 포함하고 있고, 그 코드가 클래스 선언과 매우 밀접하게 연결되기 때문.

 

 

 

 

4. 모듈명_API

class UNREALSTUDY_API AMyActor : public AActor
이 키워드는 현재 모듈의 클래스를 다른 모듈에서도 사용할 수 있게 공개하는 역할

 

 

윈도우 DLL 시스템에서는 어떤 클래스나 함수를 외부에 노출할지 지정해야 하는데,

언리얼은 ‘모듈명_API' 형태로 사용한다.

 

 

' 있으면 외부 모듈에서 접근 가능, 없으면 해당 모듈 내부용으로 제한될 수 있음 '

 

 

 

 

(추가) CreateDefaultSubobject()

생성자에서 컴포넌트를 만드는 함수 (new 대신 사용)
Box = CreateDefaultSubobject<UBoxComponent>(TEXT("Box"));

 

즉, 컴포넌트는 일반 C++ 객체처럼 new 로 만드는 것이 아니라, 언리얼이 제공하는 생성 방식을 사용해야 한다.

 

이 방식으로 생성해야

  • 언리얼 컴포넌트로 정상 등록됨
  • 에디터에 표시됨
  • 액터의 기본 서브 오브젝트로 관리됨

→ 여기에 넣는 문자열 값은 액터에 속한 컴포넌트를 구분하기 위한 Hash값으로 사용됨. (TEXT 매크로)

 

 

 

 

 

지금까지의 내용을 토대로 C++ 코드를 작성해 보면 아래와 같이 된다.

 

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"

// [ 추후 선언은 여기에 작성 ]

#include "MyActor.generated.h" // .generatred.h 파일은 항상 가장 마지막 선언 


class UBoxComponent;
class UStaticMeshComponent;

UCLASS()
class UNREALSTUDY_API AMyActor : public AActor
{
	GENERATED_BODY()
	
public:	
	AMyActor();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;

public:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Comopnents")
	TObjectPtr<UBoxComponent> Box;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Comopnents")
	TObjectPtr<UStaticMeshComponent> Body;
};

 

#include "MyActor.h"

#include "Components/BoxComponent.h"
#include "Components/StaticMeshComponent.h"


AMyActor::AMyActor()
{
	PrimaryActorTick.bCanEverTick = true;

	Box = CreateDefaultSubobject<UBoxComponent>(TEXT("Box")); // 이름 Box
	RootComponent = Box; // Box를 루트 컴포넌트로 설정

	Body = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Body"));
	Body->SetupAttachment(Box); // Box에 Body를 붙임
}

void AMyActor::BeginPlay()
{
	Super::BeginPlay();
}

void AMyActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

 

위 코드의 결과 이미지