Actor 클래스에 컴포넌트 추가
컴포넌트(component) 란? - 일종의 부품 느낌
3D메시를 할당 해주기 위해서는 액터에 추가적인 컴포넌트(component)를 붙여줘야 한다.
루트 컴포넌트와 Scene Component
- 모든 Actor는 **루트 컴포넌트 (Root Component)**를 가져야 합니다.
- 루트 컴포넌트는 액터의 트랜스폼 (위치, 회전, 크기)을 정의하는 최상위 컴포넌트이며, 모든 하위 컴포넌트가 이를 기준으로 트랜스폼이 계산됩니다.
- 보통 Scene Component를 루트 컴포넌트로 설정하여 액터의 트랜스폼을 관리하고, 그 아래에 다양한 컴포넌트를 계층적으로 붙입니다.
- Scene Component는 모든 트랜스폼 속성만 가지는 비시각적인 컴포넌트입니다.
- Scene Component는 직접적인 시각적 출력을 가지지 않지만, 다른 하위 컴포넌트들을 관리하는 기준점 역할을 할 수 있습니다.
Static Mesh Component란?
- 애니메이션이나 스켈레탈 본 없이 (즉, 움직임이 없고 단순 이동·회전만 하는) 정적 (Static) 3D 모델을 그리는 컴포넌트입니다.
- 환경 오브젝트 (건물, 바위), 아이템, 단순 기믹 오브젝트 등 “움직임이 단순하거나 없는” 오브젝트에 주로 적합합니다.
- 3D 모델을 표현하고, 물리 충돌과 관련된 기능도 제공합니다.
#pragma once // 동일 헤더가 프로젝트 곳곳에서 여러 번 포함되더라도 컴파일러가 한 번만 처리하게 함.
#include "CoreMinimal.h" // 언리얼에서 가장 기본이 되는 헤더로, 엔진 전역 타입, 매크로, 함수등을 가져옴.
#include "GameFramework/Actor.h" // AActor클래스 선언을 사용 가능하게 함.
#include "Item.generated.h" // 리플렉션 시스템
UCLASS() // 리플렉션 시스템 - 메크로
class SPARTAPROJRCT_API AItem : public AActor // A~ 접두어를 붙여 Actor클래스라는 것을 알려줌
{
GENERATED_BODY() // 리플렉션 시스템
public:
// Sets default values for this actor's properties
// 생성자
AItem();
protected:
USceneComponent* SceneRoot; // 루트 컴포넌트
UStaticMeshComponent* StaticMeshComp; // 스태틱 메시 컴포넌트
// 엑터가 월드에 완전히 배치되고, 게임 플레이가 시작할 때 한 번 호출
virtual void BeginPlay() override;
public:
// 매 프레임 마다 자동으로 호출
virtual void Tick(float DeltaTime) override;
};
// ============== cpp ===============
// 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;
// 템플릿 형태의 CreateDefaultSubobject<타입>(컴포넌트 이름)
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot); // 루트 컴포넌트 지정
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMeshComp->SetupAttachment(SceneRoot); // 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())
{
// 위에서 경로로 가져온 머터리얼을 액터에 설정
// 머터리얼은 여러개를 가져올 수 있기에 파라미터의 0으로 번호 지정
StaticMeshComp->SetMaterial(0, MaterialAsset.Object);
}
}
// Called when the game starts or when spawned
void AItem::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AItem::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
1. 언리얼 엔진 액터 라이프 사이클 (Actor Life Cycle) 가이드
액터(Actor)의 생명 주기는 언리얼 엔진 프로그래밍의 핵심입니다. 올바른 시점에 코드를 배치해야 버그를 방지하고 성능을 최적화할 수 있습니다.
- 초기화 시점 결정 (Initialization)
- 생성자, PostInitializeComponents, BeginPlay 등이 호출되는 정확한 시점을 알아야 코드를 적재적소에 배치할 수 있습니다.
- 예시: 컴포넌트 생성(CreateDefaultSubobject)은 생성자에서, 월드나 타 액터 참조는 BeginPlay에서 수행.
- 성능 관리 (Performance)
- Tick 함수는 매 프레임 호출되므로 비용이 큽니다.
- 불필요한 액터의 Tick을 비활성화하거나, 이벤트 기반(Event-Driven) 로직으로 전환하여 최적화해야 합니다.
- 안전한 리소스 정리 (Resource Cleanup)
- 액터가 소멸될 때(EndPlay, Destroyed) 메모리 해제나 상태 저장을 수행해야 합니다.
- 누락 시 메모리 누수(Memory Leak)나 크래시가 발생할 수 있습니다.
2. 라이프 사이클 진행 순서
생성 (Spawn) > 초기화 > 월드 배치 (BeginPlay) > 실행 (Tick) > 제거 (EndPlay/Destroy)
3. 주요 라이프 사이클 함수 상세
- 호출 시점: C++ 클래스 객체가 메모리에 생성될 때 단 한 번 호출됩니다.
- 특징:
- 아직 액터가 월드(World)에 등록되지 않은 상태입니다.
- 다른 액터나 월드 관련 기능(GetWorld 등)을 호출하면 위험합니다.
- 주요 용도:
- CreateDefaultSubobject를 통한 컴포넌트 생성.
- 기본 변수(Default Value) 값 설정.
3.2. PostInitializeComponents()
- 호출 시점: 액터의 모든 컴포넌트가 생성 및 초기화된 직후 자동 호출됩니다.
- 특징:
- 생성자 호출 이후이며, 각 컴포넌트가 준비된 상태입니다.
- 주요 용도:
- 컴포넌트 간의 상호작용 설정 (예: A 컴포넌트가 B 컴포넌트를 참조).
- 생성자에서 할당한 컴포넌트들의 의존성 설정.
3.3. BeginPlay()
- 호출 시점:
- 게임이 시작될 때 (Play In Editor 포함).
- 실행 중인 게임에서 SpawnActor로 액터가 생성될 때.
- 특징:
- 액터가 월드에 완전히 배치되었으며, 다른 액터들과 상호작용이 가능합니다.
- 주요 용도:
- 다른 시스템(AI, GameMode, PlayerController)과의 연동 및 초기화.
- 타이머(Timer) 시작, 델리게이트(Delegate) 바인딩.
3.4. Tick(float DeltaTime)
- 호출 시점: 매 프레임마다 호출됩니다. (PrimaryActorTick.bCanEverTick = true 설정 필요)
- 주요 용도:
- 실시간 업데이트 로직 (캐릭터 이동, 물리 연산, 추적 등).
- 주의 사항:
- 성능에 직접적인 영향을 주므로, 가능하면 이벤트 기반으로 로직을 작성하여 Tick 사용을 최소화하는 것이 좋습니다.
4. 액터 종료 및 리소스 정리4.1. Destroyed()
- 호출 시점: Destroy() 함수를 직접 호출하여 액터를 제거하기 직전.
- 주의 사항 (중요):
- 레벨 전환(Level Transition)이나 게임 종료 시에는 호출되지 않을 수 있습니다.
- 따라서 모든 정리 로직을 이곳에만 의존하는 것은 위험합니다.
- 권장 처리 항목:
- 수동으로 할당한 메모리 해제 (new / delete).
- 자동으로 해제되지 않는 자식 액터나 컴포넌트 정리.
- 액터에 종속된 사운드, 파티클의 수동 종료.
4.2. EndPlay(const EEndPlayReason::Type EndPlayReason)
- 호출 시점: 액터가 월드에서 제거되는 모든 상황 (파괴, 레벨 전환, 게임 종료 등).
- 특징:
- EEndPlayReason을 통해 종료 원인을 구분할 수 있습니다.
- Destroyed()보다 호출 보장성이 높습니다.
- 권장 처리 항목 (안전한 정리):
- 타이머 해제: GetWorldTimerManager().ClearTimer(...)
- 델리게이트/이벤트 바인딩 해제: 전역적 이벤트 등.
- 데이터 저장: 게임 진행 상황, 인벤토리 등 중요 데이터 백업.
- 남아있는 동적 할당 리소스의 최종 정리.
-
-
- 액터 제거 시 호출 보장 여부에 따라 코드를 배치하는 것이 중요합니다.
- 3.1. 생성자 (Constructor)
- 일반적인 액터의 흐름은 다음과 같습니다:
- 1. 라이프 사이클을 이해해야 하는 이유
-
'언리얼' 카테고리의 다른 글
| [2025.01.14] Unreal_7기 33 일차 | 챕터 3. C++과 Unreal Engine으로 3D 게임 개발 (0) | 2026.01.14 |
|---|---|
| [2025.01.12] Unreal_7기 32 일차 | 챕터 3. C++과 Unreal Engine으로 3D 게임 개발 (0) | 2026.01.13 |
| [2025.01.09] Unreal_7기 30 일차 | 챕터 3. C++과 Unreal Engine으로 3D 게임 개발 (0) | 2026.01.09 |
| [2025.01.08] Unreal_7기 29 일차 | 챕터 3. C++과 Unreal Engine으로 3D 게임 개발 (0) | 2026.01.08 |
| [2025.01.07] Unreal_7기 28 일차 | C++ 3 주차 프로젝트 마무리 회고록 (0) | 2026.01.07 |
