📍 1주차 3강 ~ 4강
UObject ← 모든 언리얼 클래스의 조상
├── UActorComponent ← 컴포넌트 (기능 부여용, 붙일 수 있음)
├── AActor ← 게임 월드에 존재하는 모든 액터의 기반
│ ├── APawn ← 조종 가능한 액터 (플레이어나 AI가 조종)
│ │ └── ACharacter ← 사람 형태의 폰 (걷기/점프 지원됨)
│ └── AStaticMeshActor ← 정적인 3D 모델 오브젝트
├── UGameInstance ← 게임 전반 상태 관리 (씬 바뀌어도 안 사라짐)
├── UUserWidget ← UI 요소
└── 등등...
.h → public → 다른 모듈(폴더)에서도 얘 include(참조) 가능
.cpp → private
.h .cpp → private 안에 생성 → 다른 모듈에서 include 불가능
1️⃣ .cpp .h 모두 Visual Studio에서 remove (가상 구조에서 삭제) → Save All
2️⃣ .cpp .h 모두 로컬 프로젝트 Source 폴더에서 삭제 (물리적 삭제)
3️⃣ Unreal Editor 종료 후 VS 2022에서 빌드
4️⃣ 빌드 완료 후 F5 → 에디터 실행
#pragma once // 중복 컴파일을 방지
#include "CoreMinimal.h" // 로그함수, UE 제공 기본 타입 함수
#include "GameFramework/Actor.h" // Actor Class에 관한 정보
#include "Item.generated.h" // 리플렉션 시스템
// 클래스 선언
// 이 클래스를 리플렉션 시스템에 등록하겠다
UCLASS()
class SPARTAPROJECT_API AItem : public AActor
{
GENERATED_BODY() // 매크로(리플렉션 시스템)
public:
AItem(); // 생성자
protected: // 부모 상속할 때만 접근 가능
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
};
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Item.generated.h"
"Item.generated.h", UCLASS(), GENERATED_BODY() SPARTAPROJECT_API
BeginPlay, Tick
헤더파일에서 선언한 함수들 구현
#include "Item.h"
AItem::AItem() // 생성자 구현
{
// Tick 함수 관련된 선언 (나중에 배움)
PrimaryActorTick.bCanEverTick = true;
}
void AItem::BeginPlay() // BeginPlay 구현부
{
Super::BeginPlay(); // 부모클래스의 BeginPlay 호출
}
void AItem::Tick(float DeltaTime) // Tick 구현부
{
Super::Tick(DeltaTime); // // 부모클래스의 Tick 호출
}
| 접두어 | 설명 |
|---|---|
A | Actor 클래스 (예: ACharacter, APlayerController) |
U | UObject 기반 클래스 (예: UUserWidget, UMaterial) |
F | 구조체 (Struct) (예: FVector, FHitResult) |
E | 열거형 (Enum) (예: EGameState, EWeaponType) |
T | 템플릿 클래스 (예: TArray, TMap) |
I | 인터페이스 (Interface) (예: IInteractable) |
Actor Class 만들고 월드에 배치하면
1️⃣ 메시 없음 → 아무 것도 없음 (투명)
2️⃣ Root Component 없음 → (0, 0, 0) 에 배치
➡ Actor는 최소한 하나 이상의 컴포넌트 (Root Component)있어야 제대로 Actor의 기능을 가짐
기능이 있는 하나의 부품
Static 고정된 Mesh 모델 (건물, 배경 등)Skeletal MeshStatic Mesh Model = 모양Materials Texture = 색상, 질감 등C++로 만들면 Root Component는 자동으로 리플렉션 되는데 StaticMesh는 안된다
→ 코드로 스태틱 메시 설정해줘야 함
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:
// Sets default values for this actor's properties
AItem();
protected:
// 포인터 형태로 멤버 변수 선언 (텅빈 포인터 -> 생성자에서 할당)
UPROPERTY()
USceneComponent* SceneRoot; // Root Component로 SceneComponent 생성
UPROPERTY()
UStaticMeshComponent* StaticMeshComp;
};
Item.cpp
#include "Item.h"
AItem::AItem()
{
// 포인터일 뿐이니까 SceneComponent를 생성해 연결해야 함
// <> 에 뭘 생성할 지 쓰면 됨
// () 함수인자는 컴포넌트의 이름
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
// RootComponent로 만들어주기
SetRootComponent(SceneRoot);
// StaticMesh ptr에도 연결
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
// StaticMesh는 RootComponent의 자손이니까 자손으로 붙여주기
StaticMeshComp->SetupAttachment(SceneRoot);
}
콘텐츠 브로어에서 스태틱 메시, 머티리얼 우클릭 후 Copy Reference(위치 경로 가져옴)
'/Game/Resources/Props/SM_Chair.SM_Chair'
'/Game/Resources/Materials/M_Potion_MP.M_Potion_MP'
Item.cpp
#include "Item.h"
AItem::AItem()
{
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot);
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMeshComp->SetupAttachment(SceneRoot);
// 💡 여기부터!!
// Mesh나 Resource를 load하는 클래스
// FObjectFinder가 “로드”를 수행하는 클래스
// Static 타입의 변수 선언
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Resources/Props/SM_Chair.SM_Chair"));
if (MeshAsset.Succeeded()) // MeshAsset이 성공적으로 가져와졌는지
{ // 확인하고 싶은 if문 안에
StaticMeshComp->SetStaticMesh(MeshAsset.Object); //MeshAsset의 Object를 갖고와서 할당해줌
}
// Material 할당
static ConstructorHelpers::FObjectFinder<UMaterial> MaterialAsset(TEXT("/Game/Resources/Materials/M_Potion_MP.M_Potion_MP"));
if (MaterialAsset.Succeeded())
{
StaticMeshComp->SetMaterial(0, MaterialAsset.Object); // Index 0 : 첫 번째 Material 이걸로 설정하겠다
}
}
ConstructorHelpers
| 항목 | 설명 |
|---|---|
| 🔒 생성자에서만 사용 가능 | BeginPlay, Tick에서는 못 씀 |
| 📁 경로는 정확해야 함 | 에셋 경로 틀리면 무조건 실패 |
✅ Succeeded() 꼭 체크 | 없으면 크래시 날 수도 있음 |
FObjectFinder
로드(load)
다시 언리얼로 돌아오니까 훨씬 재밌다.
C++ 처음 배웠을 때도 재밌다고 느꼈던 것 같은데.. ㅎ
튜터님께서 하나부터 열까지 알려주셔서 어느 부분을 잊었는지 다시 알 수 있었고 나름 두 달동안 공부하면서 꽤 많은 걸 배웠구나 느꼈다.
그동안은 액터를 마우스로만 만든 것 같은데 비주얼 스튜디오를 연동해서 하니까 뭔가 멋있는데 결국은 또 C++이라 얼른 익숙해져야 할 것 같다.