기타 사항
SDK 수정
FPS 템플릿은 기본 Quantum SDK와 다르게 여러 기능을 처리합니다.
기본 Quantum 및 FPS 템플릿 구현이 분기되는 모든 코드 경로는 QUANTUM_DEFAULT
if-else 정의로 표시됩니다.
C#
#if QUANTUM_DEFAULT
var matrix = Matrix4x4.TRS(t.position, t.rotation, t.localScale);
#else
var matrix = Matrix4x4.TRS(t.position, t.rotation, t.lossyScale);
#endif
Quantum SDK
Quantum SDK와 비교하여 FPS 템플릿의 Quantum 시뮬레이션에서 변경된 사항은 다음과 같습니다.
- 더 많은 매개 변수와 사용자 지정 처리를 가진 생성자를 지원하기 위해
FrameContextUser
의 재정의 RuntimeConfig
크기 제한을 1kB에서 8kB로 증가OnGameEnded()
의 모든 시스템을 비활성화- 시스템(기본적으로 실행 가능하고 사용 가능) 및 특정 코드 경로에 대한 프로파일링 타이머 추가
- 모든 기능을 지원하려면 우 특별한 경우 제외하고 frame.CreateEntity() 그리고 frame.DestroyEntity()를 통해 생성되고 제거되어야 합니다.
- API 프레임에 컴포넌트와 컨트롤러를 가져오는 몇 가지 메소드 추가
Unity 통합
Quantum SDK에 포함된 것과 비교하여 FPS 템플릿의 유니티 측면의 변경 사항은 다음과 같습니다:
- 자식과 소유자 엔티티 지원을 위한 확장된 엔티티 인스펙터.
MapData
컴포넌트 인스펙터와Quantum > Bake > Prefabs
메뉴를 통한 Bake Prefabs의 추가 옵션.- 아키텍처가 다르기 때문에 일부
QuantumRunner
함수(Init()
메소드 제외)를 무시하고Simulator
로 대체했습니다.주의: 여전히 상태 인스펙터와 같은 다른 도구들과QuantumGame
을 연결하는 데 사용됩니다. - 아키텍처가 다르기 때문에
EntityViewUpdater
를 무시하고Entities
로 대체했습니다. - 아키텍처가 다르기 때문에
EntityView
를 무시하고Entity
컴포넌트로 대체했습니다. EntityComponentBase
는 사용자 지정EntityComponent
스크립트를 상속합니다.QuantumRunnerLocalDebug
와QuantumRunnerLocalReplay
는 사용 불가입니다.- 아키텍처가 다르기 때문에 모든 기본 리플레이 스크립트를 사용자 지정 구현으로 교체했습니다.
QuantumStaticBoxCollider3D
그리고QuantumStaticSphereCollider3D
는 localScale 대신 lossyScale을 사용합니다.- 다양한 시나리오에 대한 트랜스폼 동기화 변형을 추가했습니다.
- 엔티티는 기본적으로 항상 예측 프레임에서 생성되며, 검증된 프레임에서 산란하는 작업은 시뮬레이션에서 직접 처리해야 합니다.
- SerializeReference] 특성을 가진 필드의 직렬화의 서버 측 역직렬화와의 서버 호환성을 위해 Newtonsoft.Json 대신 유니티 JsonUtility을 사용했습니다.
작업 흐름 권장 사항
다음 작업 흐름 권장 사항은 충돌을 방지하여 FPS 템플릿의 업데이트 및 업그레이드를 용이하게 하기 위한 것입니다.
- 코드와 에셋은 각자의 핵심 환경(Framework / FPS / YOUR_PROJECT)에 따라 구성되도록 항상 노력합니다. 이는 유니티 및 Quantum 솔루션 모두에 적용됩니다.
- 코어 Framework 코드를 수정하거나 확장할 경우 가능하면 부분 구현을 사용합니다. 대부분의 클래스 및 구조체는 해당 목적을 위해 부분 또는 부분적인 메소드를 가진 것으로 표시됩니다.
- 엔티티를 만들기 위해 하드코딩된 문자열보다 항상
AssetRefEntityPrototype
필드를 선호합니다. - 모든 컨트롤러가 상태 비저장입니다. 롤백 할 수 없으므로 런타임에 필드를 수정하지 마십시오. 직렬화되지 않은 정적 속성을 캐싱 할 수 있지만 할당은 원자 오퍼레이션이어야 합니다. 그렇지 않으면 경합 조건이 다중 스레드 환경에 나타납니다.
유니티 엔진 사용
UnityEngine.dll
은 서버 성능에 부정적인 영향을 미칠 수 있으므로 Quantum 솔루션과 연결할 수 없습니다. 그러나 DLL 하이재킹을 통해 데이터 구조와 속성을 사용하여 API를 모방할 수 있습니다.
동일한 서명을 가진 사용자 정의 UnityEngine.dll
을 구축하는 방법에 대한 솔루션은 REPOSITORY/extras/UnityEngine
에서 찾을 수 있습니다. 여기에는 데이터 구조와 속성이 포함되어 있으며 필요에 따라 수정할 수 있습니다. 솔루션을 구축하면 UnityEngine.dll
이 REPOSITORY/assemblies
로 복사됩니다. 이 라이브러리는 유니티에서 참조되지 않지만 원시 UnityEngine.dll
은 참조됩니다.
서버에 사용자 지정 Quantum 플러그인을 업로드할 때 이 사용자 지정 UnityEngine.dll
을 포함해야 합니다(엔터프라이즈 서버에서만 사용 가능, 주제에 대한 자세한 내용은 developer@photonengine.com 으로 문의하세요).
프레임워크 성능
다음은 저성능 모바일 장치에 대한 대상 구성 및 통계입니다:
- 시뮬레이션 속도: 30 Hz
- 목표 갱신 속도: 30 FPS
- 하드 톨러런스: 7 frames (~230ms)
- 지원 핑: ~250ms
- 원시 충돌기: 500 (75% 박스)
- 플레이어: 2 + 6 AI
- 활성 발사체: 50
- 사용자 지정 컨트롤러를 가진 기타 액터: 50
- CPU 예산: 16.667ms (프레임의 50%)
- GPU 예산: 16.667ms (프레임의 50%)
- 시뮬레이션 예산: 4.167ms
- 모든 기능이 활성화된 1개의 확인된 프레임의 시뮬레이션 시간: ~2.8ms
- 모든 기능이 활성화된 예측 프레임 1개의 시뮬레이션 시간: ~1.1ms
1 유니티 프레임 동안, 게임은 평균 1개의 검증된 Quantum 프레임과 3 - 5개의 예측 Quantum 프레임을 계산하는데, 약 7 - 8ms가 소요됩니다. 최종 성능 수치는 사용된 실제 기능 세트에 따라 크게 달라집니다. 시뮬레이션 기반 자동 와이어를 사용하지 않고 간단한 AI를 구현하거나 절대적으로 필요한 시스템만 활성화하면 많은 성능을 절약할 수 있습니다.
플레이어 수도 중요한 요소입니다. 같은 게임 씬에서 플레이어의 수가 적을수록 로직은 더 비쌀 수 있고 그 반대의 경우도 마찬가지입니다. 이것은 빈 플레이어의 자리가 인공지능 액터들로 가득 찬다고 가정하는 것입니다.
예측 프레임(최대 40개)의 스파이크를 초래하는 네트워크 상태는 극히 드문 경우입니다. 그러나 저성능 장치에서는 이러한 문제를 쉽게 피할 수 없으며 성능 프로필의 설정을 고려해야 합니다.
디버깅
로깅
FPS 템플릿의 일부 하위 시스템에는 로그가 포함되어 있습니다. 이러한 로그를 사용하면 런타임에 발생하는 작업에 대한 자세한 정보를 볼 수 있습니다.
글로벌 수준의 로깅은 GameSettings
에셋의 Severity
속성을 통해 변경할 수 있습니다. 로그 그룹 재정의를 지정할 수도 있습니다.
또는 다음 API를 통해 런타임에 로깅 수준을 변경할 수 있습니다:
- 전역적으로:
Log.SetSeverity(ELogSeverity.Warning);
- 로그 그룹 별로:
Log.SetSeverity(ELogGroup.Matchmaking, ELogSeverity.Info);
비동기화
디버깅 상태 비동기화는 특히 일회성 작업이 많은 경우 간단한 프로세스가 아닙니다.
디버깅 프로세스를 원활하게 수행하기 위한 권장 사항은 다음과 같습니다:
- 안정적이고 빠르게 재생 가능한 비동기화가 가능한 상황을 찾으려고 노력하세요.
- 첫 번째, 중간 및 마지막 시스템에서 Quantum 시뮬레이션 내의 체크섬을 계산하고 기록합니다(검증된 프레임만!). 이를 통해 기준선이 제공됩니다.
- 체크섬 차이에 따라 새로운 간격 분할을 진행합니다. 새로운 첫 번째 시스템은 다음과 같습니다.
- 체크섬이 마지막 시스템과 다른 경우 중앙 시스템을 사용합니다.
- 체크섬이 중앙 시스템과 다른 경우 마지막 시스템을 선택합니다.
- 비동기화를 일으키는 시스템이 확인될 때까지 3단계를 반복합니다.
- 전체 프로세스를 엔티티 기준으로 적용하여 컴포넌트, 컨트롤러 또는 다른 시뮬레이션의 비동기화를 유발하는 측면을 분리합니다.
일반적인 문제점
- 재시뮬레이션으로 인한 예측 엔티티 스폰 해제/재스폰: 유니티 쪽의
Entity.OnDeinitialize(bool silent)
그리고EntityComponent.OnDeinitialize(bool silent)
메소드에서silent
부울을 토글 합니다. 엔티티가 확인될 때까지 페이딩 또는 스케일링 효과로 인해 사라짐 현상이 눈에 잘 띄지 않도록 하여 이 상황을 해결하는 것이 좋습니다. Unknown managed type referenced: [quantum.code] Quantum.XYZController
: 이 오류는 프리팹 또는 씬 게임 객체에Quantum.XYZController
유형의 기존 직렬화된 인스턴스로 인해 발생합니다. 하지만 스크립트가 누락되었습니다. 일반적으로 스크립트를 제거하거나 이름을 바꾼 것과 관련이 있습니다. 이 문제를 해결하려면 오류를 트리거한 객체 / 직렬화된 파일을 찾아 해당 파일에서 직렬화된 데이터를 수동으로 제거하십시오 - 주의: 이 문제를 식별하고 해결하기 위한 툴이 포함되어 있지 않기 때문에 유니티 외부에서 수행해야 합니다. 또는 누락된 클래스를 일시적으로 다시 추가하면 필요한 객체를 다시 만들기 전에 다시 편집할 수 있습니다.