.h
, .cpp
2개의 파일이 생성됨.#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Item.generated.h"
#pragma once
#ifndef ~ #define ~ #endif
방식으로 했지만 최신 C++에선 #pragma once
권장#include "CoreMinimal.h"
FString
, TArray
)들과 매크로(UE_LOG
등), 각종 유틸 함수들이 정의되어 있음.#include "GameFramework/Actor.h"
: 액터 클래스에 대한 헤더 파일#include "Item.generated.h"
: 리플렉션 시스템 관련UCLASS()
class STUDY_API AItem : public AActor
{
GENERATED_BODY()
public:
AItem(); // 클래스 생성자
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override; // 액터 라이프 사이클 함수
// Called every frame
virtual void Tick(float DeltaTime) override; // 액터 라이프 사이클 함수
};
UCLASS()
class
STUDY_API
AItem : public AActor
AActor
상속받아 AItem
클래스 정의STUDY_API
[프로젝트명]_API
형태로 작성.GENERATED_BODY()
UCLASS()
와 짝으로, 엔진 리플렉션에 필요한 코드를 자동 생성해주는 매크로.AItem()
: 생성자BeginPlay()
Tick(float DeltaTime)
#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()
{
// 부모 클래스의 BeginPlay()를 먼저 호출
Super::BeginPlay();
}
// Called every frame
void AItem::Tick(float DeltaTime)
{
// 부모 클래스의 Tick(DeltaTime)를 먼저 호출
Super::Tick(DeltaTime);
}
#include "Item.h"
.cpp
파일에서 가장 먼저, 짝이 되는 헤더 파일을 포함해야 함.
Component
란 각각의 기능이 있는 부품들.
Actor
만으로는 원하는 객체를 만들기 어려움.Component
라는 부품을 Actor
에 붙여줌으로써 어떤 역할이나 특정 속성을 갖도록 할 수 있음.Actor
가 여러 종류의 컴포넌트를 조합하여 다양한 기능을 구현할 수 있음.StaticMeshComponent
모델을 보여주기 + AudioComponent
효과음 출력하기 + CollisionComponent
충돌 인식하기AItem
클래스를 월드에 배치해도 0,0,0 에서 안 움직인 이유Actor
를 만들었다고 끝이 아니라 컴포넌트를 붙여줘야 제대로 동작할 수 있음.Actor
가 좌표계를 인식하지 못함.RootComponent
가 없어서 좌표계를 인식하지 못한 것.Actor
는 반드시 하나 이상의 RootComponent
가 있어야 제 기능을 할 수 있음.AItem
클래스를 BP로 만들어서 배치하니까 그제서야 월드에서 움직일 수 있음.DefaultSceneComponent
가 내부에 생겼음.Root
가 생성됨.Scene Component
를 루트로 설정SceneComponent
를 쓰는 것을 권장함.Scene Component
를 루트로 설정하면, 다른 시각적 컴포넌트를 아래에 Attach
해서 관리할 수 있음.다음과 같이 사용할 컴포넌트들의 포인터 멤버 변수를 작성.
BeginPlay()
, Tick()
함수들은 필요없어서 제거함.#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Item.generated.h"
UCLASS()
class STUDY_API AItem : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AItem();
protected:
USceneComponent* SceneRoot; // 포인터를 형태로 선언
UStaticMeshComponent* Mesh;
};
USceneComponent* SceneRoot;
SceneComponent
UStaticMeshComponent* Mesh;
#include "Item.h"
// Sets default values
AItem::AItem()
{
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot);
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Model"));
Mesh->SetupAttachment(SceneRoot);
// 메쉬와 재질 설정하기
// 1. 메쉬 불러오기
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Resources/Props/SM_Chair.SM_Chair"));
// 확인 작업
if (MeshAsset.Succeeded()) // 로드 성공 확인
Mesh->SetStaticMesh(MeshAsset.Object);
// 2. 재질 불러오기
static ConstructorHelpers::FObjectFinder<UMaterialInstance> MatAsset(TEXT("/Game/Resources/Materials/M_Gem_C.M_Gem_C"));
if (MatAsset.Succeeded()) // 로드 성공 확인
Mesh->SetMaterial(0, MatAsset.Object);
}
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
CreateDefaultSubobject<T>(TEXT("컴포넌트 이름"))
SceneRoot
에 할당.SetRootComponent(SceneRoot);
Mesh->SetupAttachment(SceneRoot);
SceneRoot
의 자식으로 부착 Attach
하는 함수.static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Resources/Props/SM_Chair.SM_Chair"));
static ConstructorHelpers::FObjectFinder<T>
TEXT("/Game/Resources/Props/SM_Chair.SM_Chair")
/Script/Engine.StaticMesh'/Game/Resources/Props/SM_Chair.SM_Chair'
'/Game/Resources/Props/SM_Chair.SM_Chair'
경로 부분만 사용./Game
은 언리얼 엔진에서 프로젝트의 Content
폴더를 표시false
반환.UMaterial
, UMaterialInstance
와 같은 기능을 하는데 아예 다른 클래스가 있음..Succeeded()
false
반환.Mesh->SetStaticMesh(MeshAsset.Object);
Mesh->SetMaterial(0, MatAsset.Object);