4. Log

JUSTICE_DER·2023년 7월 21일
0

🌵UNREAL

목록 보기
35/42

🐸

언리얼 프로젝트의 헤더에 위와 같이 로그를 정의하였다.
간단하게 UE_LOG를 활용하여 모든 로그를 띄우는 것으로 이해했는데
ABCHECK같은 경우는 정확히 어떻게 동작하는 걸까?
알아본다


아래의 글을 참고하였다.


1. UE_LOG

UE_LOG(LogTemp, Warning, TEXT("Hello"));

기본적으로 UE_LOG를 사용하여 언리얼엔진에 로그를 띄울 수 있다.

  • LogTemp
    • 로그 카테고리
  • (Warning)
    • 로그 상세수준 / 로그 종류
  • TEXT
    • 로그 내용

1-1. 로그 카테고리

로그 카테고리는 출력된 로그 맨 앞에 pre-fix처럼 붙어서
어디서 발생했는지 명시해주는 역할을 한다.

(추가로 런타임과 컴파일타임의 로그 상세수준을 설정한다)

일반적으로 LogTemp라는 로그 카테고리를 사용하는데,
특정 카테고리를 지정하지 않고 그냥 임의의 장소에서 발생했음을 의미한다.

그대로 써도 로그를 띄우는데는 상관이 없지만,
정확히 어디서 발생한 로그인지 띄우는 편이 의미있을 것이다.

따라서 로그 카테코리는 위처럼
다양한 90개이상의 카테고리를 미리 이름지어놨고,
사용자가 해당 카테고리를 생성하는 것도 가능하다.

A. 사용자 정의 카테고리 생성

DECLARE_LOG_CATEGORY_EXTERN 이라는 키워드로 가능하고,
3가지의 매개변수를 포함해야 한다.

  • CategoryName
    • 새로운 카테고리로 명칭
  • DefaultVerbose
    • 런타임 동안의 Verbosity(상세 수준)
  • CompileTimeVerbose
    • 컴파일 동안의 Verbosity(상세 수준)

예시를 해석해보면 런타임동안은 Log 수준의 로깅을 적용하고, 컴파일동안은 All 수준의 로깅을 적용한다는 의미이다.

혹시 몰라서 이미 정의되어있는 로그 카테고리를 추적해보았다.
(LogActor라는 이미 정의되어있는 로그 카테고리)

로그 상세수준이 Log, Warning으로 설정된 것을 볼 수 있다.

사용자정의 로그카테고리인 Untitled가 각 로그의 맨 앞에 표시된다.

1-2. 로그 상세수준

https://docs.unrealengine.com/4.26/en-US/API/Runtime/Core/Logging/ELogVerbosity__Type/

namespace ELogVerbosity
{
	enum Type
	{

		NoLogging = 0,		// 1. 상세수준 사용하지 않음
		Fatal,				// 2. 콘솔/파일에 항상  `오류`를 표시하고,  프로그램 종료
		Error,				// 3. 콘솔/파일에 `오류`표시
		Warning,			// 4. 콘솔/파일에 `경고`표시
		Display,			// 5. 콘솔/파일에 표시
		Log,				// 6. 파일에 표시 
		Verbose,			// 7. 파일에 상세로그 표시
		VeryVerbose,		// 8. 파일에 더 상세로그 표시
		All = VeryVerbose,	// = 파일에 상세로그 표시

		//정확히 뭔지 모르겠음
		NumVerbosity,		// 1. 로그 메세지 레벨의 개수
		VerbosityMask = 0xf,// 2. 로그메세지 레벨의 비트마스크?
		SetColor = 0x40,	// 3. 색 설정
		BreakOnLog = 0x80,	// 4. 특정 로그 메세지 레벨이 출력되면 실행을 중단
	}
}

9개의 로그 상세수준이 사용되고,
그 중 자주쓰이는 아래를 표로 정리해두었다.

| Verbosity Level | Printed in Console? | Printed in Editor's Log? |                 Editor  Notes                    |
|-----------------|---------------------|--------------------------|--------------------------------------------------|
| Fatal           | Yes                 | N/A                      | Crashes the session, even if logging is disabled |
| Error           | Yes                 | Yes                      | Log text is coloured red                         |
| Warning         | Yes                 | Yes                      | Log text is coloured yellow                      |
| Display         | Yes                 | Yes                      | Log text is coloured grey                        |
| Log             | No                  | Yes                      | Log text is coloured grey                        |
| Verbose         | No                  | No                       |                                                  |
| VeryVerbose     | No                  | No                       |                                                  |

1-3. 로그 내용

로그 내용은 단순히 Printf처럼
%d %f 등을 사용하여 TEXT내에 내용을 적는다.

//1
#define CODE_LINE (FString(__FUNCTION__) + TEXT("(") + FString::FromInt(__LINE__) + TEXT(")"))

//2
#define YU_LOG(Var) UE_LOG(Untitled, Var, TEXT("%s"), *CODE_LINE)
//3
#define YU_LOG_FORMAT(Var, Format, ...) UE_LOG(Untitled, Var, TEXT("%s %s"), *CODE_LINE, *FString::Printf(Format, ##__VA_ARGS__)) //가변인자매크로

1번을 보면,
FString형의 상수 CODE_LINE을 정의한다.

  • __FUNCTION__ 매크로
    • 현재 실행중인 함수의 이름을 동적으로 문자열 상수로 표현한다
    • FString(__Function__)을 통해 FString형 문자열로 변환한다
    • 주로 로그메세지에서 사용
  • __LINE__ 매크로
    • 현재 진행중인 소스코드의 라인번호를 정수로 반환
    • 로그 메세지의 라인 번호를 반환하게 됨

2번을 보면,
매개변수를 받아서
UE_LOG의 로그 상세수준을 설정하도록 정의되었다.

그리고 로그 내용 부분은 1번을 그대로 사용하도록 만들어졌다
(FString이므로 *붙임)

3번을 보면,
매개변수와, FORMAT를 받는다.
보면 UE_LOG의 매개변수가 많은데,
TEXT부터 다 로그 내용으로 보면 될것이다.

로그를 호출하면서 지정한 내용을 매개변수도 알아서 대입해주고,
그 내용을 그대로 FString형으로 바꿔서 TEXT에 추가하는 형식이다.

결론
UE_LOG는 로그카테고리 / 로그상세수준 / 로그내용
으로 구성되어있고,
해당 요소는 변하지 않는다.
외부에서 해당 UE_LOG에 대입할 내용을 가공하고 처리과정을 바꿔도
UE_LOG는 그저 로그상세수준에 맞춰 로그내용을 로그카테고리에 맞게 표시한다.

1-4. ABCHECK

#define ABCHECK(Expr, ...) 
{if(!(Expr)) 
	{
    YU_LOG_FORMAT(
    	Error, 
    	TEXT("ASSERTION : %s"), 
    	TEXT("'"#Expr"'")); return __VA_ARGS__;
	}
}

그렇다면 위의 로그는 도대체 어떻게 작동되는 걸까??

해당 로그는 조건문을 확인하고 로그를 발생시키는데,

가장 많이 사용된 조건문은 객체가 nullptr인지 확인하고,
nullptr이라면 로그를 발생시키도록 만들어졌다.

  • 그럼 위의 ABCHECK에서 매개변수는 Expr이고,
    Expr에는 식이 들어가게 된다.

  • nullptr이 실제로 맞다면,
    Expr의 연산결과는 false가 들어갈 것이고,
    그러면 if문이 실행되게 된다.
    그러면 로그가 뜨게 된다.

  • #Expr을 한다면 해당 식이 그대로 표시가 되므로
    뭐가 문제인지 표시
    하고,
    return __VA_ARGS__를 통해 매개변수를 반환할 수도 있지만,
    반환한다기보다 그냥 해당 코드 블럭을 빠져나간다.

  • 그리고 해당 코드 블럭을 빠져나가면 코드를 계속 진행시키지만,
    return __VA_ARGS__는 예외적으로 현재 함수나 메서드가 종료되도록 하는 효과를 가진다.
    따라서 Assert()와 비슷한 효과를 낼 수 있게 된다.

2. 뷰포트에 Log 띄우기

아래를 참고하였다

UE_LOG는 단순히 디버깅용으로 로그창에 출력을 했었다.
하지만 언리얼은 뷰포트에 디버깅 로그를 띄울 수도 있다.

디버그 메시지를 뷰포트 에 출력하려면
UEngine::AddOnScreenDebugMessage()를 사용한다.

#include "Kismet/GameplayStatics.h"

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

    int32 Key = 1;
    float TimeToDisplay = 5.0f;
    FColor DisplayColor = FColor::Red;
    FString DebugMessage = TEXT("This is a debug message!");

    UGameplayStatics::AddOnScreenDebugMessage(
    Key, 
    TimeToDisplay, 
    DisplayColor, 
    DebugMessage
    );
}

해당 함수는 4가지의 변수를 받는다.

  • Key
    • 동일한 메세지를 방지하기 위한 고유키
    • -1로 설정하면 해당 메세지를 호출할 때마다 메세지를 추가함
    • 특정키로 설정하면, 특정키가 띄워져 있을때,
      현재 호출된 특정키의 메세지로 갱신됨.
      따라서 키값에 따라 단 하나의 메세지만 뜨게 된다.
  • TimeToDisplay
    • 디버그 메세지가 뷰포트에 표시될 시간을 지정
      (Sec 단위)
  • DisplayColor
    • 디버그 메세지의 색상을 지정
  • DebugMessage
    • FString형태의 출력할 TEXT 지정

추가로

  • bNewOnTop - false로 설정하면 아래서 위로출력
  • TextScale - FVector2D값 도 존재한다.

3. UE_VLog

  • 콘솔창이 아닌 뷰포트에서 띄우는 로그지만,
    단순 TEXT가 아니라 도형까지도 띄울 수 있게 된다.

추가로, 에디터의 비주얼 로거 뷰포트에서
로그가 띄워졌던 시점을 기록하고 리뷰할 수 있게 된다.

따라서 버그가 존재하는 게임플레이 영상만 보고 정확한 원인을 파악하지 못하는 경우
매우 유용하게 사용할 수 있다.

비주얼 로거 뷰포트에 뜨기 위해선
UE_VLOG 매크로를 사용해야 한다.

#include "VisualLogger/VisualLogger.h"

위는 Character에 쓰였던 비주얼로거이다.

비주얼 로거에는 다양한 매크로가 존재하고,
이를 알아야만 사용할 수 있다.

Player와 NPC가 공유하는 Character클래스에 정의되어있다.
AttackCheck에 작성되어어서 공격할때마다 vlog가 호출

추가적으로 보면 좋을 글

profile
Time Waits for No One

0개의 댓글