시각적 디버깅

이 페이지에는 Gameware NavigationWorld 및 Navigation Lab에서 제공하는 시각적 디버깅 시스템에 대한 몇 가지 세부 정보가 포함되어 있습니다.

게임에서 시각적 디버깅 시스템 사용

World에는 VisualDebugServer 클래스의 내장 인스턴스가 포함되어 있습니다. 이 클래스는 Navigation Lab과의 모든 런타임 통신을 관리합니다.

서버 활성화

World::StartVisualDebug()를 호출하여 World에 대해 VisualDebugServer를 활성화합니다.

서버 구성

VisualDebugServer를 활성화할 때 VisualDebugServerConfig 구성 오브젝트를 제공해야 합니다. 이 구성 오브젝트에는 원하는 대로 설정할 수 있는 여러 매개변수가 포함되어 있습니다.

가장 중요한 구성 매개변수는 VisualDebugServerConfig::m_serverPortVisualDebugServerConfig::m_broadcastPort 포트 설정입니다. 이러한 설정은 서버가 들어오는 연결을 수신하고 해당 가용성을 브로드캐스트하는 데 사용하는 포트를 결정합니다. Navigation Lab을 게임에 연결하는 데 문제가 있는 경우 이러한 포트가 열려 있는지 확인하십시오. 그렇지 않은 경우 게임을 실행할 때와 Navigation Lab에 연결할 때 이러한 포트를 변경하십시오.

서버 검색

World::GetVisualDebugServer()를 호출하여 World에 대해 VisualDebugServer를 검색할 수 있습니다.

서버 중지

World::StopVisualDebug()를 호출하여 언제든지 World에 대해 VisualDebugServer를 중지할 수 있습니다.

코드 예제

통합 단계 1d: 시각적 디버깅 설정 또는 Tutorial_VisualDebug.cpp 파일을 참조하십시오.

WorldElement의 정밀도

WorldElement 클래스에서 파생되는 각 오브젝트(예: 봇, 동적 장애물, TagVolume 및 관심 지점)는 각 프레임에서 네트워크를 통해 데이터를 Navigation Lab으로 자동으로 전송하여 현재 위치, 속도 등을 나타냅니다. 기본적으로 각 오브젝트는 가장 중요하게 일반적으로 사용되는 항목 정보(예: 현재 위치, 치수, 속도)만 전송하도록 구성됩니다. Navigation Lab에서 게임을 디버그할 때 Visual debug 패널에서 각 WorldElement 클래스에 대해 보려는 항목을 선택할 수 있습니다.

각 오브젝트 유형은 Navigation Lab에 추가 세부 정보도 전송할 수 있습니다. 예를 들어 봇은 해당 경로 따르기 및 동적 회피 계산 상태에 대한 세부 정보를 전송할 수 있습니다. 그러나 게임과 Navigation Lab 사이의 네트워크 통신 대역폭에 부하를 주지 않기 위해 기본적으로 이러한 세부 정보를 전송하지 않습니다.

오브젝트에 대해 기록하고 전송할 수 있는 전체 데이터 범위를 확인해야 하는 경우 게임 코드에서 해당 오브젝트가 최대 LoD(정밀도 레벨)를 사용하도록 설정할 수 있습니다. 이렇게 하면 오브젝트가 내부적으로 추가 표시 목록을 만들고 Navigation Lab으로 보내 해당 목록을 표시할 수 있도록 합니다. 이러한 추가 표시 목록은 Visual debug 패널의 Display lists 제목 아래에 나타납니다. 그러나 최대 LoD를 사용하도록 설정된 봇의 경우 추가 표시 목록은 대부분 Visual debug 패널의 Bot 제목 아래에 나타납니다. 다른 표시 목록과 유사하게 추가 표시 목록에 포함된 데이터를 표시하거나 숨길 수 있습니다.

정밀도 레벨 설정

해당 SetCurrentVisualDebugLOD() 메서드를 호출하여 언제든지 오브젝트에 대한 LoD를 설정할 수 있습니다. 다음 레벨을 전달할 수 있습니다.

  • VisualDebugLOD_None: 오브젝트에 대한 데이터가 Navigation Lab에 전송되지 않습니다.
  • VisualDebugLOD_Default: 기본 레벨의 시각적 디버깅 정보가 전송됩니다.
  • VisualDebugLOD_Maximal: 오브젝트의 추가 데이터에 대한 추가 표시 목록이 내부적으로 만들어지고 사용 중인 Navigation Lab에 전송됩니다.

ScopedDisplayLists를 사용하여 사용자 정의 3D 데이터 렌더링

ScopedDisplayList 클래스의 인스턴스를 설정하여 게임에서 Navigation Lab으로 자체 2D 모양 및 3D 볼륨을 전송할 수 있습니다.

모양 및 볼륨

ScopedDisplayList 클래스의 API는 다양한 공통 모양 및 볼륨을 만드는 방법을 제공합니다.

시각적 범례를 보려면 다음 명령을 Navigation Lab의 명령행에 입력합니다.

ToggleDrawAllShapes

수명 기간

만들어진 각 ScopedDisplayList는 해당 표시 목록을 만든 프레임이 전송된 후 Navigation Lab에 한 번만 전송됩니다. 그러나 각 표시 목록에는 Navigation Lab이 해당 데이터를 표시하는 기간을 결정하는 수명 기간이 있습니다.

Navigation Lab이 게임으로부터 해당 목록을 받을 때 단일 프레임 수명 기간을 가진 표시 목록은 한 번만 렌더링됩니다. 단일 프레임 표시 목록에 있는 데이터가 Navigation Lab에서 다중 프레임에 걸쳐 지속되는 것처럼 보이려면 모든 프레임에서 새 ScopedDisplayList 오브젝트를 다시 만들어야 합니다. 이 방법은 일반적으로 자주 변경되는 데이터에 사용됩니다. 예를 들면 다음과 같습니다.

{
    Kaim::ScopedDisplayList displayList(navWorld);
    displayList.InitSingleFrameLifespan("Display list name", "Category name");
    displayList.PushLine(gameBot->GetPosition(), Kaim::Vec3f::Zero(), Kaim::VisualColor::White);
    ... // Add more shapes here
} // Here the ScopedDisplayList is sent to the Navigation Lab.

다중 프레임 수명 기간을 가진 표시 목록도 Navigation Lab에 한 번만 전송되지만 그 이후 목록을 수정하거나 제거할 때까지 모든 프레임에서 렌더링됩니다. 게임 플레이 세션을 통해 정적으로 유지되는 데이터가 있는 경우, 이 방법을 사용하면 각 프레임에서 표시 목록을 다시 만드는 것과 관련된 계산을 수행할 필요가 없고 각 프레임에서 표시 목록을 재전송하는 작업과 관련된 네트워크 대역폭을 절약할 수 있습니다.

다중 프레임 수명 기간을 가진 표시 목록은 범주 이름과 제공한 표시 목록 이름의 조합이나 DisplayListManager에서 생성되는 숫자 ID에 의해 고유하게 식별됩니다.

이 범주와 이름 조합이나 고유 ID를 사용하면 표시 목록을 수정하거나 제거해야 할 때 해당 목록을 식별할 수 있습니다.

예를 들어 고유 ID를 명시적으로 사용하면 다음과 같습니다.

// Get a unique ID
m_displayListId = navWorld->GetDisplayListManager()->GenerateDisplayListId();

// Create a ScopedDisplayList:
{
    Kaim::ScopedDisplayList displayList(navWorld);
    m_displayListId = displayList.InitUserControlledLifespan("Display list name", "Category name", m_displayListId);
    displayList.PushLine(gameBot->GetPosition(), Kaim::Vec3f::Zero(), Kaim::VisualColor::White);
    ... // Add more shapes here
} // Here the ScopedDisplayList is sent to the Navigation Lab and rendered every frame.

...

// Modify the existing ScopedDisplayList:
{
    Kaim::ScopedDisplayList displayList(navWorld);
    m_displayListId = displayList.InitUserControlledLifespan("Display list name", "Category name", m_displayListId);
    ... // Add different shapes here
} // Here the ScopedDisplayList is sent to the NavigationLab, replacing the previous display list.

...

// Remove the existing ScopedDisplayList:
{
    navWorld->GetDisplayListManager()->RemoveDisplayList(m_displayListId); // The list is no longer displayed in the Navigation Lab.
}

Navigation Lab에서 표시 목록 표시 및 숨기기

Navigation Lab이 게임의 프레임에 대한 데이터를 표시할 때마다 Visual debug 패널의 Display lists 제목 아래에, 해당 프레임에 대해 유효한 모든 표시 목록이 표시 목록에 제공한 범주 이름에 따라 구성되어 나열됩니다. 이러한 컨트롤을 사용하여 3D 보기에서 각 표시 목록의 가시성을 토글할 수 있습니다.

예를 들어 다음 이미지에서 "MeleeCombat"는 다른 표시 목록 이름(예: "MeleeDistance", "MeleeEdgeCollector", "MeleeTarget" 및 "VisitedTriangles")을 가진 여러 표시 목록에 설정된 범주 이름입니다. 공유 범주 이름 아래 구성된 각 표시 목록은 자체 확인란이 있습니다.

표시 목록을 WorldElement와 연결

ScopedDisplayList를 특정 WorldElement(예: 봇 또는 동적 장애물)와 연결할 수 있습니다. 표시 목록이 WorldElement와 연결되면 해당 오브젝트와 관련된 다른 항목 정보와 함께 Navigation Lab에서 표시 목록의 렌더링을 제어할 수 있습니다.

WorldElement를 ScopedDisplayList와 연결하려면 해당 GetVisualDebugId() 메서드를 호출하여 WorldElement 오브젝트의 ID를 검색하고 ScopedDisplayList를 초기화할 때 해당 ID를 제공합니다. 범주 이름을 제공할 수도 있으며, 이 이름은 시각적 디버그 패널 내에서 해당 WorldElement에 대해 표시 목록을 구성하는 데 사용됩니다.

이전 섹션에서 설명한 대로 사용자 제어 수명 기간을 가진 표시 목록의 경우 해당 범주 이름 및 표시 이름을 조합하거나 해당 고유 ID를 명시적으로 지정하여 표시 목록을 식별할 수 있습니다.

예를 들면 다음과 같습니다.

KyUInt32 worldElementId = m_gameBot->GetVisualDebugId();
displayList.InitSingleFrameLifespan("Display list name", "Category name", worldElementId);

또는

KyUInt32 worldElementId = m_gameBot->GetVisualDebugId();
m_displayListId = displayList.InitUserControlledLifespan("Display list name", "Category name", worldElementId, m_displayListId);

코드 예제

통합 단계 1e: Visual Debugger로 데이터 전송을(를) 참조하십시오.

게임 카메라 따르기

게임 카메라 자세 및 매개변수를 시각적 디버거로 보내는 경우 Navigation Lab의 3D 보기에 있는 카메라가 게임 카메라의 위치 및 방향을 따르도록 할 수 있습니다.

게임 카메라를 따르려면

Navigation Lab에서 사용자 정의 명령 허용

게임에서 VisualDebugServer를 설정하여 Navigation Lab의 명령행에서 사용자 정의 명령을 허용할 수 있습니다. 이렇게 하면 디버깅 중에 게임에서 이벤트를 트리거할 수 있습니다.

코드 예제는 Tutorial_VisualDebug.cpp 파일을 참조하십시오.