언리얼 엔진 C++에서는 클래스 이름에 접두사를 붙이는 접두사 규칙이 있다.
- A (Actor 계열)
- U (Object 계열)
- F (구조체)
- T (템플릿)
- E (열거형)
// ❌ NewObject - 런타임 생성 (생성자에서 사용 안 됨)
UMyComponent* Comp = NewObject<UMyComponent>();
// ✅ CreateDefaultSubobject - 생성자에서만 사용
UMyComponent* Comp = CreateDefaultSubobject<UMyComponent>(TEXT("MyComp"));
기본 Actor 상속으로 만들었던 Item.h 파일로 보는 구조
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h" // 언리얼 엔진의 기본 타입
#include "GameFramework/Actor.h" // 액터에 대한 정보를 가지고 있는 헤더파일
#include "Item.generated.h" // 리플렉션 시스템에 관련한 헤더 파일
UCLASS() // 리플렉션 시스템에 등록해주는 키워드
// SPARTAPROJECT_API는 이 클래스를 모듈 밖으로 내보내게 해주는 일종의 매크로다.
// 빌드할 때 중요하다.
// 보통 API 앞에 이름을 붙여 쓴다.
class SPARTAPROJECT_API AItem : public AActor // A 접두어는 Actor계열이라는 의미이다. Object는 U, 구조체는 F, Enum은 E
{
GENERATED_BODY() // UCLASS와 같은 역할의 매크로
// 헤더 생성기(UHT)가 리플렉션 코드 자동 생성
public:
// Sets default values for this actor's properties
AItem();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "Item.h"
// Sets default values
AItem::AItem()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true; // Tick 함수 관련된 선언
}
// Called when the game starts or when spawned
void AItem::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AItem::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
- UCLASS(Blueprintable) // 블루프린트로 상속 가능
- UCLASS(BlueprintType) // 블루프린트 변수 타입으로 사용 가능
- UCLASS(Abstract) // 직접 인스턴스 생성 불가
- UCLASS(Notplaceable) // 에디터에서 드래그해서 놓기 불가
- UCLASS(EditInlineNew) // 에디터에서 인라인 생성 가능
UCLASS()
class AMyCharacter : public AActor
{
GENERATED_BODY()
public:
// 기본
UPROPERTY()
int32 Health;
// 에디터에서 편집 가능
UPROPERTY(EditAnywhere)
float Speed;
// 블루프린트에서 접근 가능
UPROPERTY(BlueprintReadWrite)
FString CharacterName;
// 저장됨
UPROPERTY(SaveGame)
int32 Score;
};
- UPROPERTY(EditAnywhere) // 에디터 어디서나 편집
- UPROPERTY(EditDefaultsOnly) // CDO(Class Default Object)에서만 편집
- UPROPERTY(EditInstanceOnly) // 인스턴스에서만 편집
- UPROPERTY(VisibleAnywhere) // 에디터에서 보임 (수정 불가)
- UPROPERTY(BlueprintReadOnly) // 블루프린트에서 읽기만
- UPROPERTY(BlueprintReadWrite) // 블루프린트에서 읽고쓰기
- UPROPERTY(Category = "Stats") // 에디터 카테고리 분류
Item에 스태틱 메시와 머티리얼 적용하기
// Fill out your copyright notice in the Description page of Project Settings.
#include "Item.h"
// Sets default values
AItem::AItem()
{
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot);
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMeshComp->SetupAttachment(SceneRoot);
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Resources/Props/SM_Chair.SM_Chair"));
if (MeshAsset.Succeeded())
{
StaticMeshComp->SetStaticMesh(MeshAsset.Object);
}
static ConstructorHelpers::FObjectFinder<UMaterial> MaterialAsset(TEXT("/Game/Resources/Materials/M_Metal_Gold.M_Metal_Gold"));
if (MaterialAsset.Succeeded())
{
StaticMeshComp->SetMaterial(0, MaterialAsset.Object);
}
}
ConstructorHelpers::FObjectFinder는 반드시 클래스의 생성자(Constructor) 안에서만 호출되어야 함.
void AMyActor::BeginPlay() 에서는 사용 불가.
머티리얼과 머티리얼 인스턴스 로드
머티리얼 인스턴스를 강의 내용대로 스태틱 메시에 적용하려고 하니, 오류가 뜨면서 적용되지 않았다.
C++에서 두 리소스를 로드할 때 사용하는 클래스 타입이 달라서였다.
- 머티리얼 (UMaterial):
- 정의: 쉐이더의 '원본 설계도'.
- 코드 로드: ConstructorHelpers::FObjectFinder<UMaterial>를 주로 사용.
- 머티리얼 인스턴스 (UMaterialInstanceConstant):
- 정의: 원본 머티리얼을 부모로 삼고, 수치(파라미터)만 바꾼 '사본'입니다.
- 코드 로드: ConstructorHelpers::FObjectFinder<UMaterialInstanceConstant>를 사용.
주의: 만약 코드에서 인스턴스를 불러오는데 UMaterial 타입으로 받으려고 하면 캐스팅 오류가 발생하거나 로드에 실패할 수 있음.
머티리얼 인스턴스를 받는 방법
- UMaterialInterface 사용// Fill out your copyright notice in the Description page of Project Settings. #include "Item.h" // Sets default values AItem::AItem() { SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot")); SetRootComponent(SceneRoot); StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh")); StaticMeshComp->SetupAttachment(SceneRoot); static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Resources/Props/SM_Chair.SM_Chair")); if (MeshAsset.Succeeded()) { StaticMeshComp->SetStaticMesh(MeshAsset.Object); } static ConstructorHelpers::FObjectFinder<UMaterialInterface> MaterialAsset(TEXT("/Game/Resources/Materials/M_Metal_Steel.M_Metal_Steel")); if (MaterialAsset.Succeeded()) { StaticMeshComp->SetMaterial(0, MaterialAsset.Object); } }