This document is about: FUSION 2
SWITCH TO

디버깅

플레이어/카메라의 이동은 거의 모든 게임의 핵심 요소이며 그 품질은 전반적인 게임 경험에 상당한 영향을 미칩니다.

대부분의 문제는 다음과 같은 범주에 속합니다:

  1. 더 긴 시간 동안 선명하게 볼 수 있습니다(지터, 기하에 캐릭터가 고착됨).

다음 이미지는 캐릭터 앞에 블로킹 장애물 없이 고착된 캐릭터를 보여줍니다:

Character jitters
캐릭터 지터.
Character stucks
캐릭터 고착.
  1. 짧은, 일반적으로 눈에 띄는 충격과 함께 발생하는 결함이 적습니다(텔레포트 후의 부정확한 속도 투영, 공중에 있는 동안의 스킬 작동).

다음 이미지는 캐릭터 스냅을 비교한 것입니다. 첫 번째 이미지는 수평 속도가 느려지고 텔레포트 후 다음 몇 프레임에 걸쳐 수직 이동이 추가됩니다:

Character slowed down after teleport
텔레포트 이후 캐릭터가 느려짐.
Character remains speed after teleport
텔레포트 이후 캐릭터의 속도가 잔여.
  1. 시각적으로 분명하게 눈에 띄지 않거나 설명하기 어려우며 주관적인 느낌에 영향을 줍니다(원시 입력 적용, 경사면을 배경으로 걸을 때 수평 이동 누출).

다음 이미지는 카메라 회전에 적용되는 원본과 매끄러운 마우스 입력을 비교한 것으로, 매끄러운 게임 경험과 버터처럼 부드러운 게임 경험의 차이를 만듭니다:

원시 입력 후 카메라 회전
원시 입력 후 카메라 회전.
매끄러운 입력 후 카메라 회전.
매끄러운 입력 후 카메라 회전.

고급 KCC는 위의 모든 문제를 보다 빠르게 디버깅하고 심층적으로 분석할 수 있는 도구를 제공합니다.

런타임 정보

KCC 컴포넌트는 플레이 모드일 때 추가 버튼과 정보를 보여줍니다:

런타임 버튼
런타임 버튼.
  • 입력 권한 - 🟢 객체가 입력 권한을 가지고 있을 경우 녹색.
  • 상태 권한 - 🟢 객체가 상태 권한을 가지고 있을 경우 녹색.
  • 고정 데이터 사용 / 렌더링 데이터 사용 - 드로잉 및 런타임 정보 값에 사용할 데이터를 선택.
  • 드로우 버튼들은 아래의 드로잉 섹션에서 설명되어 있습니다.
  • 로그 버튼은 로그에 사용됩니다.
실행 정보
실행 정보.

자체-기술 속성 중에 KCC 인스펙터에는 접을 수 있는 부분이 있습니다:

  • 로컬 프로세서 - 활성 로컬 프로세서 목록으로, KCC.LocalProcessors에 해당합니다.
  • 네트워크 변경자 - 모든 활성 변경자의 목록으로 KCCData.Modifiers에 해당합니다.
  • 네트워크 충돌 - 모든 활성 네트워크 충돌의 목록으로 (NetworkObject 컴포넌트를 가진 콜라이더), KCCData.Collisions에 해당합니다.
  • 무시하는 콜라이더 - 현재 무시되는 콜라이더의 목록으로 KCCData.Ignores에 해당합니다.
  • 충돌 히트 - 일부 메타데이터가 포함된 마지막 물리 쿼리의 모든 콜라이더(네트워크 및 비네트워크) 목록으로, KCCData.Hits에 해당합니다
  • 실행 스택 (스테이지 + 프로세서) - 스테이지(회색, 황색) 및 프로세서(하늘색)의 마지막 실행 순서.

게임 객체(콜라이더/프로세서)가 있는 모든 엔트리는 빠른 조회가 가능하며, 엔트리 패턴은 Name (Type)입니다.

로그

다음을 통해 로그를 활성화할 수 있습니다:

  1. 실행 시 KCC 게임 객체를 선택 후 KCC 인스펙터 내 Logs 버튼 클릭.
  2. KCC에서 제공하는 로그 메소드 사용:

C#

public override void OnStay(KCC kcc, KCCData data)
{
    // Logs current KCC and KCCData state to console.
    kcc.Dump();
    
    // Enable logs for duration (in seconds) passed as parameter. The output is same as Dump().
    // Useful to debug behavior after activation of an ability so it doesn't spam conosle too much.
    kcc.EnableLogs(1.0f);
    
    // Logs info message to console with frame/tick metadata.
    kcc.Log("Info");
    
    // Logs warning message to console with frame/tick metadata.
    kcc.LogWarning("Warning");
    
    // Logs error message to console with frame/tick metadata.
    kcc.LogError("Error");
}

메시지 양식은 다음과 같습니다:

[시간] [프레임][틱][이름] 메시지

이며, 각각

  • 시간 - 기본 유니티 로그 타임 스탬프.
  • 프레임 - 엔진 프레임 번호 (Time.frameCount)
    • 붉은색 - 홀수 프레임.
    • 파란색 - 짝수 프레임.
  • - Fusion 시뮬레이션 틱 (Runner.Tick)
    • 붉은색 - 재시뮬레이션이 활성화.
    • 노란색 - 포워드 시뮬레이션이 활성화.
    • 녹색 - 렌더가 활성화.
  • 이름 - KCC 게임 객체의 이름.
  • 메시지 - 사용자 정의 메시지.

다음 이미지는 kcc.Log("Info");를 사용하여 유니티 콘솔에서 색상으로 구분된 출력을 보여줍니다.

로그 출력
로그 출력.

여기에서 볼 수 있는 것?

  1. 프레임 5839 - 포워드 틱 1개(노란색) + 렌더(녹색) 시뮬레이션 실행.
  2. 프레임 5840 - 렌더만 실행(다음 고정 틱을 시뮬레이션하기에 충분한 시간이 경과하지 않음).
  3. 프레임 5841 - 서버에서 새 데이터가 도착하고 틱 1371, 13721373이 재시뮬레이션(빨간색)되고 1 포워드 틱 + 렌더 시뮬레이션이 실행됩니다.
  4. 프레임 5842 - 렌더만 실행(다음 고정 틱을 시뮬레이션하기에 충분한 시간이 경과하지 않음).
  5. 프레임 5843 - 3개의 포워드 틱(아마도 마지막 프레임에서 히컵이 있었습니다) + 렌더 시뮬레이션 실행.

드로잉

드로임은 다음으로 활성화시킬 수 있습니다:

  1. 실행 시 KCC 게임 오브젝트 선택 후 KCC 인스펙터 내 Draw 버튼 클릭.
  • 드로우 경로 - 고정 및 렌더 업데이트의 경로를 보여줍니다.
    • 붉은 점 - 고정 업데이트에서 위치.
    • 녹색 점 - 렌더 업데이트의 위치.
    • 붉은 선 - 고정 업데이트에서 베이스와 타깃 위치를 연결합니다.
    • 녹색 선 - 렌더 업데이트에서 베이스와 타깃 위치를 연결합니다.
    • 보라색 선 - 탐지된 예측 오류 - 마지막 렌더 위치 대 타임스탬프가 동일한 고정 위치 사이의 예상 위치.
    • 파란색 선 - 최신 시뮬레이션 상태에서 적용된 예측 오류.
    • 노란 선 - 예측 보정.
렌더 인터폴레이션 경로
렌더 인터폴레이션 경로.
렌더-예측 경로
렌더-예측 경로.

⚠️ 렌더 인터폴레이션 경로의 위치에 주목하세요. 방향이 변경되면 원하지 않는 효과가 발생할 수 있습니다(이 경우 하드 그라운드 히트 대신 평활화된 랜딩).

  • 드로우 속도 - 캐릭터의 속도(벡터 크기는 인스펙터에서 조정 가능)를 보여줍니다. 다양한 표면에서 이동할 때/장애물을 통과할 때/불필요한 속도를 감지할 때 상대적으로 속도를 비교하는데 유용합니다.
드로우 속도
모든 프레임 드로우 속도.
  • 착륙 정상 그리기 - 착륙 정상을 나타냅니다. 움직임 계산에 오류가 있을 수 있습니다.
착륙 정상 그리기
착륙 정상 그리기.
  • 착륙 탄젠트 그리기 - 착륙 탄젠트를 보여줍니다. 움직임 계산에 오류가 발생할 수 있습니다.
착륙 탄젠트 그리기
착륙 탄젠트 그리기.
  • 착륙 스내핑 그리기 - 착륙 스내핑 이벤트를 표시합니다(캐릭터가 착륙 상태를 유지할 정도로 빠르게 떨어지지 않고 뚝뚝 떨어짐). 이는 일반적으로 돌기 위를 걷거나 가파른 경사로를 걸을 때 발생합니다.
착륙 스내핑 그리기
착륙 스내핑 그리기.
  • 착륙 그리기 - 착륙 이벤트를 표시합니다. 이렇게 하면 캐릭터가 예기치 않게 착륙 상태를 잃어 애니메이션에 영향을 주는 문제를 드러내는 데 도움이 될 수 있습니다.
    • 녹색 - 착륙함.
    • 붉은색 - 착륙 지점 잃어버림.
점프시 착륙
점프시 착륙.
  • 스텝 업 그리기 - 스텝 업 이벤트를 보여줍니다. 이 기능을 사용하면 스텝 업 기능이 통과 가능해야 하거나 해서는 안 되는 장애물을 통과하는 캐릭터를 담당하는지의 여부를 빠르게 확인할 수 있습니다.
    • 녹색 - 스텝 업이 시작되었습니다.
    • 빨간색 - 스텝 업이 종료되었습니다.
Draw stepping up
스텝 업 그리기.
  • 이동 방향 그리기 - 이동 방향을 표시합니다. 이를 통해 다양한 표면에서 원하지 않는 이동을 식별하고 이동 계산에 오류를 드러낼 수 있습니다.
이동 방향 그리기
이동 방향 그리기.
  1. KCC에서 제공하는 그리기 메소드들을 사용하여 사용자 지정 일회성 이벤트 디버깅에 유용합니다.

C#

public override void OnStay(KCC kcc, KCCData data)
{
    // Draw a color-coded line for 10 secons at current KCC position.
    // Red    = resimulation tick.
    // Yellow = forward simulation tick.
    // Green  = render update.
    kcc.DrawLine(10.0f);

    if (kcc.IsInForwardUpdate == true)
    {
        // Draw a blue line for 10 secons at current KCC position.
        kcc.DrawLine(Color.blue, 10.0f);
    }
}

레코더와 그래프

실시간 디버깅을 위한 도구도 중요하지만 기록 및 후향적 분석을 위한 도구도 중요합니다.

다음 이미지는 기록된 세션과 확대된 세부 정보를 보여줍니다. 그래프는 완전히 탐색할 수 있고 읽기 쉽습니다.

저장된 세션
저장된 세션.
저장된 세션 상세 정보
저장된 세션 상세 정보.

주요 이점은 다음과 같습니다:

  • ✅ 높은 수준에서 그래프를 신속하게 검사하고 일부 로컬 문제를 발견할 수 있습니다.
  • ✅ 다른 빌드에서 가져온 것과 나중에 비교하여 저장할 수 있습니다. 이렇게 하면 새로운 릴리즈에 도입된 버그를 쉽게 식별할 수 있습니다.
  • ✅ 문제가 있는 특정 사용자에 대해 원격으로 녹화가 가능하며 게임 플레이 세션 중에 특이한 값이 있는지 확인할 수 있습니다.
  • ✅ 테스터는 프로덕션 빌드와 함께 모든 세션을 자동으로 녹음하고 버그 리포트에 녹음을 첨부할 수 있습니다.

고급 KCC는 다음과 같은 레코더 컴포넌트를 제공합니다:

  • KCC Recorder - KCCKCCData 속성을 기록합니다.
  • Camera Recorder - Camera.main 위치와 회전을 기록합니다.
  • Transform Recorder - Transform 위치와 회전을 기록합니다.
  • Player Recorder - TransformCamera.main의 위치와 회전을 기록합니다.

다음 그림은 샘플 프로젝트1인칭 전문가 플레이어 프리팹에 대한 레코더입니다.

플레이어 레코더
플레이어 레코더.

각 레코더는 활성화 시 고유한 파일을 생성합니다. 파일은 루트 프로젝트 폴더(편집기에서 플레이할 때)에서 생성되거나 빌드 폴더에서 직접 생성됩니다.

⚠️ 값을 올바른 시각으로 볼 수 있도록 올바른 레코더 타입을 설정하는 것이 매우 중요하며, 사용 가능한 값은 다음과 같습니다:

  • Frame - 그래프의 X축은 Time.frameCount의 선형 표현입니다. 파일은 (Frame)으로 끝납니다
  • Engine Time - 그래프의 X축은 Time.unscaledTime의 선형 표현으로 파일은 (EngineTime)으로 끝납니다.
  • Monitor Time - 그래프의 X축은 모의 모니터 시간의 선형 표현입니다. 파일은 (Runner.Tick)으로 끝납니다.
  • Simulation Tick - 그래프의 X축은 순방향 시뮬레이션에서 Runner.Tick을 선형으로 표현한 것으로 파일은 (SimulationTick)으로 끝납니다.

⚠️ Monitor Time은 특정 디스플레이 리프레시 속도를 시뮬레이션하여 그래픽 카드 버퍼에 렌더링 된 데이터가 아닌 현재(실제로 보는 것) 값을 나타내는 특수 레코더 타입입니다. 프레임 버퍼가 완벽하게 매끄러운 움직임이 플레이어의 눈에 매끄러운 것으로 인식된다는 보장은 없습니다.

다음 이미지는 288Hz 모니터와 360Hz 모니터에서 플레이어에게 제공되는 288FPS 게임 플레이에서 카메라 룩 회전을 비교한 것으로, 플레이 시 눈에 잘 띕니다.

288Hz 모니터에서 288 FPS
288Hz 모니터에서 288 FPS.
360Hz 모니터에서 288 FPS
360Hz 모니터에서 288 FPS.

레코드된 파일을 분석하기 위해서:

  1. 파이썬을 설치합니다.
  2. 다음의 파이썬 패키지들을 설치합니다:
    • pandas
    • plotly
    • chart_studio
  3. 위에 언급한 레코더 스크립트를 사용하여 몇 가지 레코딩을 합니다.
  4. Assets\Photon\FusionAddons\KCC\Utilities\Recorders\CreateHTMLGraphs.py 스크립트를 기록된 파일의 폴더로 복사합니다.
  5. python 스크립트를 실행하고 모든 HTML 파일이 생성될 때까지 기다립니다.
생성된 HTML 파일들
생성된 HTML 파일들.

사용자 지정 레코드 생성하기:

C#

[DefaultExecutionOrder(31510)]
public class CustomRecorder : StatsRecorder
{
    protected override void GetHeaders(ERecorderType recorderType, List<string> headers)
    {
        // Write headers.
        headers.Add($"Value Name");
    }

    protected override bool AddValues(ERecorderType recorderType, StatsWriter writer)
    {
        // Write values.
        writer.Add($"{0.0f:F4}");

        return true;
    }
}

레코드 실행하기:

C#

public class Player : MonoBehaviour
{
    public CustomRecorder _recorder;

    public void SomeMethod()
    {
        // Starts recording with default settings.
        _recorder.SetActive(true);

        // Starts recording with specific type.
        _recorder.SetActive(ERecorderType.EngineTime);

        // Stops recording, flushes all values and closes the file.
        _recorder.SetActive(false);
    }
}
Back to top