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);
}
}

Root Component
루트 컴포넌트는 무조건 리플렉션 시스템에 등록되어 언리얼 에디터에서 항상 보인다.
StaticMesh Component
리플렉션 시스템에 등록하지 않으면 언리얼 에디터에서 볼 수 없다.
메시 및 머티리얼 파일의 경로 가져오기
content Browser에서 우클릭 > copy reference: 해당 파일의 주소 복사
// 헤더
// 카테고리 이름
// 기본 로그 심각도: 이 카테고리는 해당 레벨 이상 메시지만 출력
// All: 필요하면 모든 로그 활성화 가능
DECLARE_LOG_CATEGORY_EXTERN(LogMyActor, Log, All);
// cpp
DEFINE_LOG_CATEGORY(LogMyActor);
커스텀 로그 카테고리를 다른 파일에서도 쓰려면 해당 파일 헤더를 포함해야 한다. 규모가 커지면 별도의 Util 헤더에 선언하고 쓰는 것이 편리하다.
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
객체 자체를 변경하는 건 불가능하지만 내부 속성 정도는 수정 가능
출처: 스파르타코딩 내일배움캠프