본문 바로가기

언리얼 + cpp

언리얼C++ 2일차(UE_LOG, 라이프 사이클 함수)

UE_LOG

	UE_LOG(LogTemp, Warning, TEXT("My Log!"));

UE_LOG(로그 카테고리, 로그 수준, 출력할 메세지) 로 로그를 출력할 수 있다.

로그 카테고리는 로그를 구분하기 위한 이름이다. 여기서는 LogTemp라는 엔진에서 기본 제공하는 임시 카테고리를 사용했다.

로그 수준은 로그의 중요도와 색상을 나타내는데 Warning은 노란색, Display는 흰색, Error는 빨간색 등 다양하게 있다.

출력할 메세지는 TEXT매크로를 사용하여 유니코드로 만들어야한다. 형식 지정자(%d, %f 등)를 사용해서 변수 값도 출력 가능.

 

컴파일 후 액터를 뷰포트에 배치하고 실행해보면 Output Log에 My Log!가 출력된다.

여기서 필터를 사용해서 원하는 카테고리의 로그만 볼 수 있다.

필터를 LogTemp로 하니 많았던 로그들이 안보이고 LogTemp카테고리만 보인다.

필터를 이용해서 대규모 프로젝트같은 경우 필요한 고유한 카테고리를 만들어서 로그 카테고리 관리를 할 수 있다.

고유한 카테고리를 정의하고 로그 추가하기

헤더파일에서 include 아래, Class 위쪽 공간에

DECLARE_LOG_CATEGORY_EXTERN(LogJIN, Warning, All);를 선언하면 카테고리가 추가된다.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Item.generated.h"

DECLARE_LOG_CATEGORY_EXTERN(LogJin, Warning, All);

UCLASS()
class STUDY5_API AItem : public AActor
{

LogJIN : 카테고리의 이름 부분

Warning : 이 카테고리는 이 로그 수준 이상의 로그만 출력하도록 설정한다.

All : 필요하면 나중에 모든 로그를 활성화 할 수 있도록 허용한다.

헤더에서 선언한 후 소스에서도 DEFINE_LOG_CATEGORY(LogJin);을 선언해 줘야 카테고리를 사용할 수 있다.

#include "Item.h"

DEFINE_LOG_CATEGORY(LogJin);

AItem::AItem()
{
이 카테고리를 다른 클래스에서도 사용하려면 이 헤더 파일을 포함 시키면 되며 관련이 없는 헤더를 포함시키기엔 비효율적이므로 카테고리만 관리하는 별도의 공용 헤더에 선언해두는 경우가 많다.

고유 카테고리를 사용해서 로그를 출력해보자.

void AItem::BeginPlay()
{
	Super::BeginPlay();

	UE_LOG(LogTemp, Warning, TEXT("My Log!"));
	UE_LOG(LogJin, Error, TEXT("HELLO JIN!"));
}

LogJin도 필터를 사용해서 볼 수 있다.

라이프 사이클

생성자 - 메모리에 생김. 딱 한번 호출됨.

PostInitializeComponents() - 컴포넌트가 완성된 직후 호출. 컴포넌트끼리 데이터를 주고받거나 상호작용이 필요할 때

BeginPlay() - 배치(스폰) 직후

Tick(float DeltaTime) - 매 프레임마다 호출됨.

Destroyed() - 삭제 되기 직전에 호출된다.(리소스 정리)

EndPlay() - 게임 종료, 파괴, 레벨 전환

 

헤더에 라이프 사이클 함수를 선언한다.

	virtual void PostInitializeComponents() override;
	virtual void BeginPlay() override;
	virtual void Tick(float DeltaTime) override;
	virtual void Destroyed() override;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

언제 호출 되는지 확인해보기위해 각 함수 별로 다른 메세지를 출력하도록 한다.

#include "Item.h"

DEFINE_LOG_CATEGORY(LogJin);

AItem::AItem()
{
	UE_LOG(LogJin, Warning, TEXT("%s Constructor"), *GetName());
}

void AItem::PostInitializeComponents()
{
	Super::PostInitializeComponents();

	UE_LOG(LogJin, Warning, TEXT("%s PostInitializeComponents"), *GetName());
}

void AItem::BeginPlay()
{
	Super::BeginPlay();

	UE_LOG(LogJin, Warning, TEXT("%s BeginPlay"), *GetName());
}

void AItem::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

void AItem::Destroyed()
{
	UE_LOG(LogJin, Warning, TEXT("%s Destroyed"), *GetName());

	Super::Destroyed();
}

void AItem::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	UE_LOG(LogJin, Warning, TEXT("%s EndPlay"), *GetName());
	
	Super::EndPlay(EndPlayReason);
}

Tick은 매 프레임마다 호출되므로 다른 함수의 로그 출력을 방해하기 떄문에 넣지 않았다.

Destroyed와 EndPlay함수는 출력이 끝난 후 호출되도록 부모의 함수(Super::)를 UE_LOG 뒤에 작성했다.

 

컴파일을 하고 언리얼 에디터에서 Item을 뷰포트에 배치하면 생성자가 호출되고

실행을 하면 생성자와 BeginPlay와 PostInitializeComponents가 호출된다.

실행중이 아닐 때 액터를 클릭하고 삭제를 하면 Destroyed가 호출되고 실행중에 삭제를 하면 Destroyed와 EndPlay가 호출된다.

실행중에 삭제