9.1 기록과 추적

유용한 디버깅 도구 중 하나는 printf 디버깅이다.

 

9.1.1 Win32 함수 OutputDebugString()을 통한 서식화된 출력

printf와 달리 outputDebugString은 서식화된 출력을 지원하지는 않는다.(일반 문자열만 출력할 수 있다.)

보통의 윈도우 기반 엔진에서는 서식화된 문자열을 따로 만들고 그 문자열을 outputDebugString으로 출력하는 함수를 따로 구현한다.

 

9.1.2 출력 수준 (Vervosity)

코드의 주요한 위치에 printf 구문들을 힘들게 집어넣었는데 볼일이 끝났다고 그냥 지우기에 아까운 경우

출력 수준을 커맨드라인 입력으로 받거나 런타임에 동적으로 지정하도록 할 수 있다.

출력 수준이 최소(보통 0)으로 되어 있으면 치명적 오류 메세지만 출력되고, 출력 수준을 높일수록 더 많은 printf 구문들이 출력을 하도록 만들 수 있다.

쉽게 구현하는 방법은 전역 변수에 출력 수준을 저장하고 출력 함수의 인자로 출력 수준을 받아 조건에 따라 출력을 처리하도록 하는 것이다.

 

9.1.3 채널

디버그 출력을 채널로 분류할 수 있다면 애니메이션 시스템으로 부터 오는 메세지는 애니메이션 채널에 물리 시스템에서 오는 메세지는 물리 채널에 오도록 만들면 보기에 좋다.

디버그 출력 함수에 채널을 지정할 수 있는 인자를 받아 구현할 수 있다.

 

9.1.4 출력을 파일에도 보내기

로그 파일에 디버그 출력을 담으면 문제가 발생한 후에도 원인을 파악할 수 있다.

 

9.1.5 강제 종료 리포트

게임이 강제 종료(Crash) 되는 경우

대부분의 운영체제에서는 최상단 예외 핸들러를 설치해 대부분의 강제 종료 상황을 캐치할 수 있고 예외 핸들러 함수 안에서 필요한 정보를 출력할 수 있다.

출력하면 좋을 정보들

ㄴ 강제 종료 시의 현재 레벨

ㄴ 강제 종료 시 플레이어 캐릭터의 월드 공간 위치

ㄴ 강제 종료 시 플레이어의 애니메이션과 액션 상태

ㄴ 강제 종료 시 실행하고 있던 게임플레이 스크립트

ㄴ 콜 스택 정보

ㄴ 엔진의 모든 메모리 할당자의 상태

ㄴ 기타 강제 종료의 원인을 파악하는데 필요하다고 판단한 정보들

ㄴ 강제 종료 순간의 스크린 샷

 

9.2 디버그 정보 그리기 기능

9.2.1 디버그 정보 그리기 API가 가져야 하는 기능

ㄴ API는 간단하고 사용하기 쉬워야 한다.

ㄴ 기본 단위(선분, 구, 점(작은 구), 좌표계의 축, 경계 박스, 서식화된 문자열)을 그릴 수 있어야 한다.

ㄴ 기본 단위들을 월드 공간 혹은 스크린 공간에 그릴 수 있어야 한다.

ㄴ 깊이 테스트를 켜거나 끌 수 있어야 한다. (장면의 다른 물체에 가려지거나 가려지지 않거나)

ㄴ 코드의 어느 곳에서나 디버그 정보 API를 호출할 수 있어야 한다. 대부분의 렌더링 엔진들에서는 렌더링할 기하 형상들을 매 프레임의 마지막 부분에 전달하기 때문에 모든 디버깅 요청을 큐(디버그 정보 그리기 큐)에 모아 놓았다가 나중에 처리할 수 있게 해야 한다.

ㄴ 모든 디버그 기본 단위에는 수명이 있어야 한다. 프로그래머가 초 단위로 수명을 지정할 수 있어야 한다.

ㄴ 디버그 정보 그리기를 담당하는 시스템은 디버그 기본 단위의 수가 많은 경우라도 효과적으로 처리할 수 있어야 한다.

 

9.3 인게임 메뉴

소스코드를 고치고 컴파일 링크 과정을 거쳐 게임을 다시 실행하기보다 게임 실행 중에 즉시 바꿔 개발 시간을 줄이기 위해 사용한다.

ㄴ 전역으로 선언된 변수 값을 조정하는 기능

ㄴ 임의의 함수를 호출할 수 있는 기능

 

9.4 인게임 콘솔

인게임 메뉴와 비슷한 역할을 한다. 직접 타이핑해야 한다는 점이 다르다.

전역 엔진의 설정을 조정하거나 명령을 내릴 수 있다.

인게임 콘솔에서 스크립트 언어를 지원하는 경우 콘솔을 통해 스크립트로 할 수 있는 모든 것을 할 수 있다.

예를 들면 마인크래프트 /명령어 

 

9.5 디버그 카메라와 게임 일시 정지

게임을 한 프레임 단위로 실행하는 기능

ㄴ 슬로우 모션은 애니메이션, 파티클 효과, 물리 및 충돌 동작, AI 행동 등을 자세히 살펴보는데 도움이 된다.

게임이 정지한 상태에서 자유롭게 게임 월드를 돌아다니며 장면의 모든 구성을 살펴 볼 수 있는 기능

ㄴ 렌더링 엔진과 카메라 컨트롤이 정상적으로 작동하는 동안 게임의 논리적 클록만 정지함으로써 구현

 

9.6 치트

게임 플레이를 테스트하기 위해 게임 규칙을 깨버릴 수도 있어야 한다.

 = 마인크래프트 크리에이티브 모드

 

9.7 스크린샷과 무비 캡처

ㄴ 화면을 캡처해서 .bmp나 .jpg, .tga 포맷으로 디스크에 저장하는 기능, 비디오 메모리에 있는 프레임 버퍼를 메인 메모리로 복사하는 그래픽 API를 사용한다.

 

스크린샷에 추가 기능을 제공한다면

ㄴ 디버깅 그리기 단위를 포함할지의 여부

ㄴ 헤드업 디스플레이를 포함할지의 여부

ㄴ 고해상도의 스크린샷을 저장할 것인지의 여부

ㄴ 카메라 애니메이션을 사용하여 스크린샷을 여러개 찍을 것인지 여부

 

9.8 게임 내 프로파일링

상당수의 엔진들은 어느 정도의 인게임 프로파일링 툴을 제공한다.

측정하고 싶은 코드(함수 호출)에 프로그래머가 표시를 하고 구분할 수 있는 이름을 부여한다. 프로파일링 툴은 이렇게 표시된 코드들의 실행 시간을 CPU의 정밀 타이머로 측정한 후 결과를 메모리에 저장한다. 이렇게 측정한 결과는 헤드업 디스플레이를 통해 보여준다. 실행 시간을 보여줄 때  cpu cycle 수, 마이크로초 단위, 전체 프레임에서 차지하는 비율로 보여줄 수 있다.

 

9.9 인게임 메모리 상태와 누수 감지

게임 엔진들은 자체적으로 메모리 감지 툴을 구현한다. 이런 툴의 역할은 각 엔진 하부 시스템에서 사용하는 메모리 양을 보여주고 메모리 누수 여부를 감지한다.

 

게임이 실제로 사용하는 메모리 양을 정확히 파악하기 어려운 이유

1. 외부 라이브러리를 사용하는 경우 라이브러리의 할당자를 원하는 할당자로 대체할 수 없는 경우 메모리 할당/해제를 추적할 수 없다.

2. 비디오 메모리의 사용량을 추적하기는 힘들다. DirectX API가 비디오 메모리의 할당과 사용에 대한 세부적 내용을 개발자로부터 격리시키기 때문이다.

3. 할당자의 종류가 많고 할당자들은 게임이 시작할 때 큰 단위로 메모리를 미리 할당하고(new로) 자체적으로 관리하기 때문에 실제로 쓸 만한 정보를 얻으려면 각 할당자의 메모리 블록 안에서 할당과 해제를 추적해야 한다.


게임을 개발하는 도중에 사용하는 PC나 콘솔은 보통 최소 요구 사양 PC나 실제 콘솔보다 RAM도 많고 성능이 좋기 때문에 실제 상황에서는 메모리가 부족한데 잘 실행되는 경우가 있다. 이를 위해 메모리가 부족 상태가 되면 게임 엔진은 메모리가 부족하다는 메세지를 띄워주어야 한다.

 

메모리 추적 시스템을 이용해 리소스 자원을 불러오는데 실패한 경우 대체 리소스를 입혀주거나 불러오지 못한 리소스의 이름을 출력하는 시스템을 만들 수도 있다. 이는 프로그래머가 문제를 빠르게 파악할 수 있게 도움을 준다.

+ Recent posts