안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다.

이번 영상에서는 언리얼 엔진의 뷰포트에 바로 로그를 띄우는 방법을 알아봅시다.

 

사용 엔진 버전 : 4.26

 

타임라인

0:00 인트로

0:35 블루프린트에서 뷰포트에 로그 출력하기

2:22 C++ 클래스에 뷰포트에 로그 출력하기

3:35 블루프린트 로그 기능을 C++ 클래스에서 사용하기

4:49 아웃트로

반응형

Tutorial (2)

유니티 에디터의 화면 구성

 

작성 기준 버전 :: 2018.3.1f1

 

[본 튜토리얼은 유튜브 영상으로도 시청하실 수 있습니다]

 

유니티 에디터로 프로젝트를 처음으로 열면 화면이 아래의 이미지와 같이 구성되어 있다.

 

 

 

이 화면의 구성에 대해서 하나씩 알아보도록 하자.

 

 

씬(Scene) 뷰

 

 

에디터 레이아웃 구성의 한 가운데 있는 것은 Scene 뷰다. 유니티에서 씬(Scene)이라는 개념은 일종의 맵(Map)이나 레벨(Level)에 해당한다. 씬 뷰는 이러한 씬에 배경을 꾸미기위해 소품이나 배경 건물 등을 배치하는데 사용된다.

 

 

하이어라키(Hierarchy) 창

 

 

씬 뷰의 좌측에 있는 하이어라키 창은 씬에 배치되어 있는 오브젝트들을 보여준다. 가장 상단에 SampleScene이라는 이름으로 현재 열려있는 씬의 이름이 표시되고, 그 아래에 그 씬에 포함된 오브젝트들이 나타난다. 기본적으로 배치되어 있는 오브젝트는 Main Camera라는 이름의 카메라와, Directional Light라는 이름의 조명이다.

 

 

프로젝트(Project) 창

 

 

프로젝트 창은 현재 프로젝트에 포함된 텍스처나 모델링, 스크립트, 씬 등의 애셋(Asset)을 보여주는 창이다. 개발 경험이 많지 않은 경우에는 프로젝트 창에 애셋들이 추가되는 대로 중구난방으로 쌓아두는 일이 많은데, 애셋들을 적절하게 분류해서 정리해두는 버릇을 들여두는게 나중에 필요한 애셋을 찾거나 불필요한 애셋을 정리할 때 큰 도움이 되며, 개발 속도에도 긍정적인 영향을 미칠 것이다.

 

 

인스펙터(Inspector) 창

 

 

인스펙터 창은 지금은 아무 내용이 없지만, 하이어라키 창에서 씬에 배치된 오브젝트나 프로젝트 창에서 프로젝트에 포함된 애셋을 선택하면 그것에 대한 자세한 정보를 보여주는 역할을 한다.

 

 

하이어라키 창에서 메인 카메라 오브젝트를 선택하고 인스펙터 창을 보면 메인 카메라 오브젝트의 자세한 정보를 확인하고 수정할 수 있게 된다.

 

 

게임(Game)

 

 

씬 창 뒤에 탭으로 되어 있는 게임 창 탭을 선택하면 씬 창이 뒤로 전환되고 게임 창이 앞으로 나온다.

 

게임 창은 씬 창과 같이 씬을 보여주는 역할을 하지만, 게임 창은 씬 창과는 다르게 카메라가 보여주는 것만을 볼 수 있는 창이다. 즉, 실제 게임에서 보게 될 장면을 보여주는 창이다.

 

 

 

 

 

콘솔(Console) 창

 

 

콘솔 창은 개발도중에 발생한 에러나 경고, 개발자가 기능을 테스트하거나 값을 체크하기 위해 출력시킨 로그 등이 출력되는 창이다. 출력된 로그를 더블클릭하면 비주얼 스튜디오가 열리고 해당 로그가 출력된 스크립트의 위치로 이동하게 된다.

 

로그의 종류

 

 

유니티 엔진에서 로그는 크게 일반 로그, 경고 로그, 에러 로그로 나누어지고, 일반 로그는 데이터의 값이나 진행 상황, 상태를 체크하기 위해 사용되는 로그이고, 경고 로그는 치명적이지는 않지만 수정할 것을 권장하는 로그이며, 에러 로그는 게임이 정지하거나 기능에 심각한 이상이 발생하는 상황에 대한 로그이다.

 

세부적인 버튼의 내용은 다음과 같다.

 

 

뒤의 세 개 버튼은 각각 일반 로그, 경고 로그, 에러 로그 보기 버튼이며, 해당 버튼을 눌러서 원하는 종류의 로그만 볼 수 있다.

 

 

일반 로그만 활성화한 상태이다.

 

 

경고 로그만 활성화한 상태이다.

 

 

 

에러 로그만 활성화한 상태이다.

 

 

Clear 버튼은 현재까지 출력된 로그들을 모두 지운다.

 

 

 

Collapse 버튼은 같은 내용의 로그가 여러 번 출력되면 여러 줄로 표시하지 않고 한 줄로 표시하며 같은 내용의 로그가 몇 번이나 출력되었는지를 보여주는 기능이다. 이것은 로그의 순서가 중요하지 않고, 출력되었느냐 혹은 몇 회나 출력되었는지가 중요한 경우에 사용하게 된다.

 

Clear on Play 버튼은 에디터에서 플레이 버튼을 눌렀을 때, 남아있는 로그를 모두 지우고 플레이를 시작하게 만든다. 남아있는 이전에 띄운 로그가 남아있다면 플레이 중에 뜨는 로그가 보기 힘들어지는 경우가 많기 때문에 사용한다.

 

Error Pause 버튼은 플레이 도중에 에러 로그가 발생하면 플레이를 일시정지 시키는 버튼이다. 에러가 나도 플레이가 계속되면 에러가 발생하는 순간을 놓칠 수도 있기 때문에 에러가 발생한 순간을 잡아내기 위해서 사용하는 기능이다.

 

Editor 버튼은 에디터의 로그를 출력한다는 뜻의 버튼이다. 나중에 모바일 게임을 개발하다보면 APK로 빌드한 앱을 모바일 기기에 설치해서 컴퓨터와 연결하고 실행해서 실시간으로 로그를 보기위해서 사용되는 버튼이다.

 

 

애셋 스토어(Asset Store) 창

 

 

 

 

애셋 스토어 창은 다른 개발자들이 만든 게임 개발용 애셋들을 구매할 수 있는 창이다. 대규모 개발팀이나 회사는 게임에 필요한 모든 리소스들을 개발할 여력이 있겠지만, 소규모 개발팀이나 1인 개발자는 모든 리소스를 만들어내기 매우 어렵기 때문에 다른 사람이 만든 애셋을 구매해서 사용하면 더 빠르게 게임을 개발할 수 있다는 장점이 있다.

 

 

그 외의 창들

 

유니티 엔진에는 방금 화면 구성에서 소개한 창들 외에도 많은 종류의 창들이 존재한다.

 

 

에디터 상단의 메뉴 바에서 Window 메뉴를 클릭해서 드롭다운 메뉴를 펼치면 숨겨진 창들의 목록을 보고 필요한 창을 열어서 사용할 수 있다.

 

 

그 외의 버튼들

 

 

이 버튼들은 씬에 배치된 오브젝트를 이동, 회전, 크기 조절을 하는데 사용되는 버튼들이다.

 

 

이 버튼들은 에디터에서 게임을 실행, 일시정지, 한 프레임씩 넘기기를 하는 버튼이다.

 

 

좌측 버튼부터 순서대로, 팀단위 작업을 위한 유니티 콜라보(Collaborate) 버튼, 유니티가 제공하는 서비스 버튼, 계정 관리 버튼, 씬 창에서 보이기 원하는 레이어를 선택하는 버튼, 유니티 에디터의 레이아웃 버튼이다.

 

 

유니티 에디터 레이아웃 수정하기

 

유니티 에디터의 화면 구성은 사용자가 편한 방식으로 레이아웃을 수정할 수 있다.

 

 

위치를 수정하려고하는 창의 탭을 드래그해서 에디터에서 완전히 떼어내거나 다른 곳에 배치할 수 있다.

 

 

완전히 떼어낸 하이어라키 창

 

 

다른 위치에 배치한 하이어라키 창

 

 

각자 사용하기 편한 방식으로 레이아웃을 배치해보자.

 

 

수정한 레이아웃 저장하기

 

수정한 레이아웃은 저장해두고 언제든지 다시 불러올 수 있다. 에디터 우측 상단 구석에 Default 버튼을 클릭하면 드롭다운 메뉴 중에 Save Layout... 버튼을 클릭하면 수정한 레이아웃의 이름을 지어줄 수 있는 대화상자가 뜬다.

 

 

좌측부터 게임, 씬, 콘솔이 한 묶음으로 묶여있고, 그 다음엔 하이어라키와 프로젝트, 마지막으로 인스펙터로 나열되서 3-2-1로 배치되어 있으니 이 레이아웃의 이름을 Countdown이라고 저장하겠다.

 

 

레이아웃을 저장하고 나면 Default로 되어있던 버튼이 Countdown으로 되어있으며 추가한 Countdown 레이아웃이 드롭다운 목록에 추가되어 있는 것을 확인할 수 있다. 이렇게 레이아웃을 저장해두면, 레이아웃이 바뀌어도 언제든지 손쉽게 자주 사용하는 레이아웃으로 돌아올 수 있다.

 

 

반응형

로그 출력하기

 

작성버전 :: 4.20.3

 

로그는 개발중에 여러가지 피드백을 얻기 위해서 중요한 도구다. 그렇기 때문에 항상 새로운 언어, 새로운 엔진 등을 배울 때는 거기서 어떤 방식으로 로그를 출력하는지 알아두는 것이 좋다. 이번에는 언리얼 엔진 4에서 로그를 출력하는 방법을 알아보자.

 

 

로그가 출력되는 출력 로그 탭 열기

 

 

 

우선은 로그를 출력하는 법을 배운 이후에 로그가 출력될 로그 탭을 여는 방법에 대해서 배워보자.

 

- 창 -> 개발자 툴 -> 출력 로그 (Window -> Developer Tools -> Output Log) 항목을 선택한다.

 

 

 

지시대로 출력 로그(Output Log) 항목을 선택하면 출력 로그 탭이 열리는 것을 확인할 수 있다. 에디터에서 우리가 출력하도록 명령한 로그들은 저 출력 로그 탭에서 출력될 것이다.

 

 

간단한 사용법

 

UE_LOG(LogTemp, Log, TEXT("Log Message"));

 

위의 코드를 사용하는 것으로 간단하게 로그를 출력할 수 있다. 언리얼에서 로그 기능은 매크로 함수로 정의 되어있으며, 매개변수는 앞에서부터 순서대로 로그 카테고리(Log Category), 로그 상세 수준(Log Verbosity Level), 로그 내용이다.

 

 

로그 상세 수준(Log Verbosity Level)

 

로그 상세 수준의 종류는 다음과 같다.

 

  • Fatal
Fatal 수준 로그는 항상 콘솔 및 로그 파일에 출력되며 로그가 비활성화된 경우에도 작동이 중단된다.
  • Error
Error 수준 로그는 콘솔 및 로그 파일에 출력되며, 이 로그는 기본적으로 빨간색으로 표시된다.
  • Warning
Warning 수준 로그는 콘솔 및 로그 파일에 출력되며, 이 로그는 기본적으로 노란색으로 표시된다.
  • Display
Display 수준 로그는 콘솔및 로그 파일에 출력된다.
  • Log
Log 수준 로그는 로그 파일에는 출력되지만, 게임 내의 콘솔에서는 출력되지 않지만, 에디터의 출력 로그 탭을 통해서는 계속 출력된다.
  • Verbose
Verbose 수준의 로그는 로그 파일에는 출력되지만, 게임 내의 콘솔에는 출력되지 않는다. 일반적으로 자세한 로깅 및 디버깅에 사용된다.
  • VeryVerbose
VeryVerbose 수준의 로그는 로그 파일에는 출력되지만, 게임 내의 콘솔에는 출력되지 않는다. 이 수준의 로그는 일반적으로 대량의 로그를 출력하는 상세한 로깅에 사용된다.

 

 

로그 상세 수준 중에 자주 사용될 에러, 경고, 로그 수준을 사용해서 로그를 출력하면 위의 이미지와 같이 로그가 출력된다.

 

Fatal 수준의 로그는, 출력되거나 컴파일 혹은 빌드할 때 코드가 실행되는 상황이라면 충돌 리포트를 띄우지만 이것은 의도된 충돌이기 때문에 로그 파일이나 충돌 호출 스택(Crash call stack)을 확인하면 된다.

 

 

 

 

 

로그 카테고리(Log Category)

 

로그 카테고리는 출력된 로그가 어떤 시스템에서 발생한 로그인지 알려주는 역할을 한다. 위의 간단한 사용법 파트에서는 이 로그 카테고리에 LogTemp를 넣어서 사용했는데, 이것은 특정한 카테고리에 속하지 않고 임시로 띄우는 로그라는 의미다. 언리얼 엔진에서는 이러한 카테고리를 90개 이상을 기본적으로 제공한다.

 

 

 

어떤 카테고리에서 로그가 발생했는지 알려줄 수 있기 때문에 로그 출력 코드를 작성할 때, 제대로 된 카테고리를 분류해서 넣어주기만 한다면 로그가 제공하는 정보가 좀 더 상세해질 수 있다.

 

 

커스텀 로그 카테고리(Custom Log Category)

 

언리얼 엔진에서 제공하는 로그 카테고리 이외에 개발자가 필요한 카테고리를 직접 만들어서 사용할 수 있다.

 

만약, 당신의 프로젝트 이름이 MyGame이라면 비주얼 스튜디오의 솔루션 탐색기에서 MyGame.h와 MyGame.cpp를 찾아서 다음과 같이 추가하면 된다.

 

MyGame.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

DECLARE_LOG_CATEGORY_EXTERN(LogMyGame, Log, All);

 

MyGame.cpp

// Fill out your copyright notice in the Description page of Project Settings.

#include "MyGame.h"
#include "Modules/ModuleManager.h"

IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, MyGame, "MyGame" );

DEFINE_LOG_CATEGORY(LogMyGame);

 

그리고 추가한 로그 카테고리를 사용할 때는 아래의 예시 코드와 같이 사용할 소스 파일에 MyGame.h를 포함한뒤 사용하면 된다.

 

MyActor.cpp

// Fill out your copyright notice in the Description page of Project Settings.

#include "MyActor.h"
#include "Engine.h"
#include "MyGame.h"

// Sets default values
AMyActor::AMyActor()
{
     // 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;

    UE_LOG(LogMyGame, Log, TEXT("My Log"));
}

 

 

 

 

 

로그 포맷(Log Formatting)

 

로그를 작성할 때, 로그의 내용이 고정되어 있는 경우보다, 상황이나 데이터의 내용에 따라 유동적으로 바뀌는 경우가 많다. 그렇기 때문에 간단한 사용법 파트의 예시처럼 고정된 문자열 방식이 아니라 포맷팅을 통해서 원하는 데이터의 내용 등을 고정된 로그의 내용과 함께 출력되도록 해야한다. 언리얼 엔진에서 로그 포맷팅을 하는 방법은 CPP에서 문자열 포맷팅하는 방법과 같다.

 

일반 메시지

UE_LOG(LogTemp, Log, TEXT("Log Message"));

 

FString

 

언리얼 엔진에서 기본적으로 사용되는 문자열 클래스는 FString이다. 로그에서 %s는 TCHAR* 타입을 받는다. 이것은 *FString에 대응한다.

UE_LOG(LogTemp, Log, TEXT("Character Name :: %s"), *MyCharacter->GetName());

 

bool

UE_LOG(LogTemp, Log, TEXT("Character is Die :: %s"), MyCharacter->IsDie ? TEXT("true") : TEXT("false"));

 

int

UE_LOG(LogTemp, Log, TEXT("Character HP :: &d"), MyCharacter->Hp);

 

float

UE_LOG(LogTemp, Log, TEXT("Character Stamina :: %f"), MyCharacter->Stamina);

 

FVector

 

FVector는 언리얼 엔진에서 위치를 표현하는 클래스이다.

UE_LOG(LogTemp, Log, TEXT("Character Location :: %s"), MyCharacter->GetActorLocation().ToString());

 

FName

UE_LOG(LogTemp, Log, TEXT("Character FName :: &d"), MyCharacter->GetFName().ToString());

 

여러 자료형 한번에 로그로 출력하기

UE_LOG(LogTemp, Log, TEXT("CharacterName :: &s / HP :: &d / Stamina :: %f"), *MyCharacter->GetName(), MyCharacter->Hp, MyCharacter->Stamina);

 

추가로...

 

bool 같은 논리 변수는 로그로 출력하는 과정이 조금 번거롭기 때문에, 로그를 자주 사용한다면 이러한 번거로운 과정을 간소화하기 위해서 로그를 위한 클래스로 래핑해서 사용하는 것도 추천해볼만하다.

 


 

참고

 

Unreal Engine 4 Wiki - Logs, Printing Messages To Yourself During Runtime (https://wiki.unrealengine.com/index.php?title=Logs,_Printing_Messages_To_Yourself_During_Runtime&action=edit)

반응형
  1. 익명 2021.05.07 15:19

    비밀댓글입니다

    • 익명 2021.05.12 09:46

      비밀댓글입니다

    • 익명 2021.05.16 15:50

      비밀댓글입니다

로그(Log) 출력시 스택 트레이스(Stack trace) 관리하기


로그(Log)는 개발자들에게 없어서는 안될 중요한 동반자다. 개발자는 로그를 통해서 코드가 제대로 동작하는지, 데이터 값들이 정상인지 등을 확인할 수 있다. 만약 로그가 없다면, 개발자는 버그를 찾아내는데 더 많은 고생을 하게 될 것이다.



유니티에서는 이러한 로그를 출력할 때, 위의 이미지처럼 개발자가 출력하고자하는 로그의 내용과 함께 로그가 출력된 코드의 위치를 알려주는 스택 트레이스 역시 함께 보여준다. 로그를 출력하도록 설정해놓았다면 빌드한 어플이케이션에서도 로그가 찍힐 때 스택 트레이스 역시 함께 출력되도록 되어있다.


위의 이미지는 간단한 테스트 코드이기 때문에 스택 트레이스가 3줄 밖에 안되지만 본격적으로 개발에 들어간 이후에는 스택 트레이스가 기본적으로 4-5줄에서 많은 10여줄을 넘는 경우가 자주 발생한다.


에디터에서라면 스택 트레이스와 로그가 분리되어서 출력되기 때문에 로그를 읽는데는 큰 문제가 없지만 윈도우 빌드에서 나오는 로그 파일이나, 안드로이드로 빌드된 어플리케이션으로 로그캣에서 로그를 볼때는 로그 바로 아랫줄에 스택 트레이스가 바로 출력되기 때문에 로그를 제대로 읽기가 매우 어려워진다.


물론 코드의 어느 지점에서 에러 로그가 발생했는지 확인해야하는 로그라면 스택 트레이스가 출력되는게 좋지만, 로그가 출력된 위치보다는 출력되는 내용이 더 중요한 로그라면 스택 트레이스는 출력되지 않는 편이 로그의 가독성을 더 높혀줄 것이다.


Application.SetStackTraceLogType(LogType logType, StackTraceLogType stackTraceLogType);


Application 클래스의 SetStackTraceLogType() 함수를 통해서 스택 트레이스의 출력 수준을 결정할 수 있다.


LogType 열거형은 스택 트레이스 수준을 설정할 로그의 종류를 의미한다. 로그의 종류는 다음과 같다.


LogType.Error
LogType.Assert
LogType.Warning
LogType.Log
LogType.Exception


StackTraceLogType은 스택 트레이스의 출력 수준을 의미한다. 스택 트레이스 출력 수준의 종류는 다음과 같다.


StackTraceLogType.None;
StackTraceLogType.ScriptOnly;
StackTraceLogType.Full;


스택 트레이스 타입을 수정하지 않았을 때, 유니티의 기본 수준은 ScriptOnly이다. None으로 설정하면 스택 트레이스가 전혀 출력되지 않고 Full로 설정하면 기존의 스택 트레이스보다 더 자세한 정보를 제공하는 스택 트레이스가 출력된다.





응용


스택 트레이스 타입을 변경하는 순간부터 모든 로그에 스택 트레이스 타입이 변경되기 때문에, 제대로 다루지 않으면 스택 트레이스가 필요한 로그에서 스택 트레이스가 출력되지 않거나 혹은 그 반대의 경우가 발생할 수 있다.


필요한 상황에서만 스택 트레이스를 켜고 끄기 위한 방법으로는 Debug 클래스를 래핑해서 사용하는 방법이 있다.


using UnityEngine;

public static class Debug
{
    public static void Log(object message, StackTraceLogType stackTraceLogType = StackTraceLogType.ScriptOnly)
    {
        Application.SetStackTraceLogType(LogType.Log, stackTraceLogType);
        UnityEngine.Debug.Log(message);
    }
}


반응형

+ Recent posts