언리얼 에디터에서 Actor 클래스를 public 으로 생성하게 되면 .h
가 public 폴더에, .cpp
가 private 폴더에 생긴다.
반대로 Actor클래스를 private으로 생성하게 되면 .h
, .cpp
가 private 폴더에 생긴다.
Actor를 생성하고 에디터에서 월드에 배치하게 되면 3D 모델이 눈에 보이지 않는다. 그 이유는 3D 메시를 설정하지 않았기 때문이다. 3D 메시를 할당해주기 위해서는 Actor에 추가적인 Component를 붙여줘야 한다.
컴포넌트는 언리얼 엔진에서 Actor가 어떤 역할을 하거나 특정 속성을 갖도록 만들어주는 부품(파츠) 개념이다.
Item.h
파일에서 다음과 같이 포인터 멤버 변수 추가 #pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Item.generated.h"
UCLASS()
class SPARTAPROJECT_API AItem : public AActor
{
GENERATED_BODY()
public:
AItem();
protected:
// 루트 컴포넌트를 나타내는 Scene Component 포인터
USceneComponent* SceneRoot;
// Static Mesh Component 포인터
UStaticMeshComponent* StaticMeshComp;
};
Item.cpp
#include "Item.h"
AItem::AItem()
{
// Scene Component를 생성하고 루트로 설정
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot);
// Static Mesh Component를 생성하고 Scene Component에 Attach
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMeshComp->SetupAttachment(SceneRoot);
}
CreateDefaultSubobject<T>(TEXT(""))
<T>
로 생성할 컴포넌트의 유형을 지정한다."StaticMesh
, "SceneRoot"
는 각 컴포넌트의 식별 이름이 된다.TEXT()
매크로는 문자열을 유니코드로 처리하기 위한 것으로, 언리얼 엔진 코드 표준에서 권장한다.SetRootComponent(SceneRoot)
SetupAttachment(SceneRoot)
StaticMeshComp
를 SceneRoot
에 부착한다.StaticMeshComp
는 SceneRoot
의 하위 컴포넌트로 동작하며, SceneRoot의 트랜스폼 변화에 따라 움직인다..uasset
파일로 관리된다.#include "Item.h"
AItem::AItem()
{
// Scene Component를 생성하고 루트로 설정
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot);
// Static Mesh Component를 생성하고 Scene Component에 Attach
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMeshComp->SetupAttachment(SceneRoot);
// Static Mesh를 코드에서 설정
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Resources/Props/SM_Chair.SM_Chair"));
if (MeshAsset.Succeeded())
{
StaticMeshComp->SetStaticMesh(MeshAsset.Object);
}
// Material을 코드에서 설정
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<T>
TEXT("/Game/Resources/Props/SM_Chair.SM_Chair")
리소스의 경로를 나타낸다. 리소스의 경로를 가져오려면 아래와 같이 해당하는 에셋을 우클릭하고 Copy Refernece를 해서 붙여넣기를 한다.
단 /Game
여기서부터만 입력하면 되고, 앞의 경로는 삭제를 해준다.
/Game
은 Unreal Engine에서 프로젝트의 Content
폴더를 나타낸다.
.Succeeded()
SetStaticMesh()
, SetMaterial()
StaticMeshComp
에 설정한다.StaticMeshComp
의 특정 머터리얼 슬롯에 적용한다. 위의 예제에서는 첫번째 슬롯(Index 0)에 Material이 설정되었다.C++로 액터를 배치하고 실제 3D모델을 화면에 나타낼 수 있도록 배울 수 있어서 좋았다. 실체화를 위해서는 액터에 컴포넌트를 생성하고 root component를 지정해주는것. 그래야만 transform이 가능하다는 것 까지 원리를 이해하고 코드로 구현까지 가능하게 되었다.
하지만 오늘 배운 점에서도 문제점이 있다면 머터리얼과 스태틱메시를 지정하는데 있어 중간에 파일경로가 바뀌면 재사용이 매우 좋지 않다는 점이다. 특히 여러 클래스가 같은 스태틱메시나 머터리얼을 사용하고 있을 때, 파일경로가 바뀐다면 일일이 찾아가서 경로지정한 코드를 수정해주어야만 한다. 그래서 경로를 동적으로 추적하는 Asset Manager나 데이터테이블을 이용해서 경로를 지정하는 방법이 있다는데 이번에 배운걸 제대로 체득하고 나면 자세히 알아보아야 겠다.