[내일배움캠프/UE] Actor C++ 클래스

김세희·2025년 7월 1일

✍️Today I Learned

  1. Actor 클래스 컴포넌트 추가
  2. 커스텀 로그 카테고리 정의
  3. Actor 라이프 사이클
  4. 리플렉션 시스템

Actor 클래스 컴포넌트

  1. Actor 클래스에 컴포넌트 멤버 변수 추가
  2. 스태틱 메시 컴포넌트에 메시 및 머티리얼 할당

Item.h

#pragma once

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

UCLASS()
class CH3_PROJECT_API AItem : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AItem();

protected:
	USceneComponent* SceneRoot;
	UStaticMeshComponent* StaticMeshComp;
};

Item.cpp

#include "Item.h"

// Sets default values
AItem::AItem()
{
    // CreateDefaultSubobject : 컴포넌트 생성해주는 함수, 컴포넌트 타입, 컴포넌트 이름 입력 
    SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));    
    // 루트 컴포넌트 설정
    SetRootComponent(SceneRoot);

    StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
    // 루트 컴포넌트에 메시 붙이기
    StaticMeshComp->SetupAttachment(SceneRoot);

    // StaticMesh 설정
    // ConstructorHelpers : 리소스를 로드하는 클래스
    // FObjectFinder : 오브젝트를 찾음
    static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Resources/Props/SM_Star_C.SM_Star_C"));
    if (MeshAsset.Succeeded()) 
    {
        StaticMeshComp->SetStaticMesh(MeshAsset.Object);
    }

    // Material 설정
    static ConstructorHelpers::FObjectFinder<UMaterial> MaterialAsset(TEXT("/Game/Resources/Materials/M_Power_Sphere.M_Power_Sphere"));
    if (MaterialAsset.Succeeded()) 
    {
        // Material은 여러개를 설정할 수 있으므로 어떤 메시의 재질인지 인덱스로 표현
        StaticMeshComp->SetMaterial(0, MaterialAsset.Object);
    }
}

  1. Root Component
    루트 컴포넌트는 무조건 리플렉션 시스템에 등록되어 언리얼 에디터에서 항상 보인다.

  2. StaticMesh Component
    리플렉션 시스템에 등록하지 않으면 언리얼 에디터에서 볼 수 없다.

  3. 메시 및 머티리얼 파일의 경로 가져오기
    content Browser에서 우클릭 > copy reference: 해당 파일의 주소 복사


커스텀 로그 카테고리 정의

// 헤더
// 카테고리 이름
// 기본 로그 심각도: 이 카테고리는 해당 레벨 이상 메시지만 출력
// All: 필요하면 모든 로그 활성화 가능
DECLARE_LOG_CATEGORY_EXTERN(LogMyActor, Log, All);
// cpp
DEFINE_LOG_CATEGORY(LogMyActor);

커스텀 로그 카테고리를 다른 파일에서도 쓰려면 해당 파일 헤더를 포함해야 한다. 규모가 커지면 별도의 Util 헤더에 선언하고 쓰는 것이 편리하다.


Actor 라이프 사이클

라이프 사이클 함수

1. 생성자
오브젝트가 메모리에 생기면서 딱 한 번 호출된다.
아직 월드에 액터가 등장하지는 않았을 가능성이 크다.
여러가지 초기화 작업 담당(컴포넌트 생성)

2. PostInitializeComponents()
액터의 컴포넌트들이 이미 초기화가 되고 호출도 된 직후에 호출되는 함수
컴포넌트간의 상호작용 처리 담당

3. BeginPlay()
액터가 월드에 배치, 스폰이 된 직후 호출
액터들 간의 상호작용

4. Tick(float DeltaTime)
매 프레임마다 호출
너무 무거운 로직을 넣으면 성능을 떨어뜨리기 때문에 주의해야 한다.

5. Destroyed()
액터가 삭제되기 직전에 호출된다. 명시적으로 이 함수가 호출된게 아닌 게임 종료나 레벨 전환 시점에는 호출되지 않는다.
리소스 정리

6. EndPlay(const EEndPlayReason::Type EndPlayReason)
게임 종료, 파괴(Destroyed), 레벨 전환 시점에 호출
const EEndPlayReason::Type EndPlayReason : enum 타입 변수로 어떤 이유로 이 액터의 라이프 사이클이 끝나는지에 대한 정보가 담겨 있다.

라이프 사이클 로그 출력

#include "Item.h"

// 로그 카테고리 정의
DEFINE_LOG_CATEGORY(LogSparta);

// Sets default values
AItem::AItem()
{
    UE_LOG(LogSparta, Warning, TEXT("%s Constructor"), *GetName());
}

void AItem::PostInitializeComponents() 
{
    UE_LOG(LogSparta, Warning, TEXT("%s PostInitializeComponents"), *GetName());
    Super::PostInitializeComponents();
}

void AItem::BeginPlay() 
{
    // 부모 클래스 함수 호출
    // 안하면 에러 남
    Super::BeginPlay();
    // 로그 출력
    UE_LOG(LogSparta, Warning, TEXT("%s BeginPlay"), *GetName());
}

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

void AItem::Destroyed() 
{
    // 부모 클래스 함수 호출되면 삭제될 수 있어서 그 전에 작성
    UE_LOG(LogSparta, Warning, TEXT("%s Destroyed"), *GetName());
    Super::Destroyed();
}

void AItem::EndPlay(const EEndPlayReason::Type EndPlayReason) 
{
    // 부모 클래스 함수 호출되면 삭제될 수 있어서 그 전에 작성
    UE_LOG(LogSparta, Warning, TEXT("%s EndPlay"), *GetName());
    Super::EndPlay(EndPlayReason);
}

리플렉션 시스템

// 리플렉션 시스템에 필수적인 헤더
// 항상 마지막에 있어야함 아니면 에러
#include "Item.generated.h"

C++ 클래스는 언리얼 에디터에서 클래스 디폴트 수정이 불가능 하다. 옵션에 따라 상속받은 블루프린트 클래스에서는 가능하다.
언리얼 에디터에 있는 디테일창은 인스턴스 디테일이고 클래스 디폴트랑은 다르다

UPROPERTY(): 멤버 변수 리플렉션 시스템 등록
UFUNCTION(): 멤버 함수 리플렉션 시스템 등록

둘다 안에 인자 없으면 언리얼 에디터에 보이는건 아니지만 엔진이 해당 함수나 변수의 존재를 알게 된다.

🔸UPROPERTY() SPECIFIER
1. VisibleAnyWhere : 수정 불가능 읽기 전용
2. EditAnyWhere : 클래스 디폴트, 인스턴스 둘 다 수정 가능
3. EditDefaultsOnly : 클래스 디폴트만 수정 가능하고 인스턴스는 수정 불가
4. EditInstanceOnly : 클래스 디폴트는 수정 안되고 인스턴스에서만 가능
5. BlueprintReadOnly : 블루프린트에서 읽기 전용. get만 가능
6. BlueprintReadWrtie : get, set 가능

🔸UFUNCTION() SPECIFIER
1. BlueprintCallable : 블루프린트에서 해당 함수 호출 가능
2. BlueprintPure : 블루프린트에서 값만 반환 받음
3. BlueprintImplementableEvent : 블루프린트에서 구현했지만 C++에서도 호출 가능

📌VisibleAnywhere, BlueprintReadOnly

객체 자체를 변경하는 건 불가능하지만 내부 속성 정도는 수정 가능

출처: 스파르타코딩 내일배움캠프

0개의 댓글