영상을 불러오지 못했습니다

FastArraySerializer 변경·삭제 개수 제한 경고 다루기

795 단어
4 분
FastArraySerializer 변경·삭제 개수 제한 경고 다루기

FFastArraySerializer 배열에서 한 frame에 많은 원소를 바꾸거나 지우면 아래 경고가 나타난다.

NumDeletes > GetMaxNumberOfAllowedDeletionsPerUpdate()
Header.NumChanged > GetMaxNumberOfAllowedChangesPerUpdate()

문제 현상#

서버의 배열 최종 상태가 맞더라도 client가 일부 변경을 받지 못하는 경우가 있다. replication 중 제한 초과 경고가 반복되기도 한다. inventory 초기화, 대규모 reset, reconnect snapshot처럼 많은 원소를 한꺼번에 처리하는 경로에서 주로 드러난다.

적용 범위#

Unreal 프로젝트에서 FFastArraySerializer 또는 Iris의 fast array 지원을 사용할 때 해당한다. 기본 허용 개수와 조정 방법은 엔진 버전에 따라 달라진다. 설치한 source에서 GetMaxNumberOfAllowedChangesPerUpdate와 GetMaxNumberOfAllowedDeletionsPerUpdate 구현을 확인한다.

원인#

Fast Array delta는 변경을 한 update에 무제한으로 싣지 않는다. 지나치게 큰 packet, 잘못된 ID 또는 악의적인 payload를 막으려고 개수에 제한을 둔다. 배열 전체 재생성이나 불필요한 dirty 표시는 이 제한을 빠르게 소진한다.

  • 배열 전체를 지우고 같은 내용을 다시 추가한다.
  • 매 tick 같은 원소를 불필요하게 MarkItemDirty한다.
  • 원소 추가·수정 후 dirty 표시를 빠뜨렸다가 한 번에 몰아서 처리한다.
  • 대량 snapshot과 작은 gameplay delta를 같은 replication 경로에 싣는다.

재현 및 진단#

  1. update 직전의 추가·수정·삭제 개수와 배열 길이를 로그에 기록한다.
  2. 원소별 ReplicationID가 안정적으로 유지되는지 확인한다.
  3. 추가·수정 시 MarkItemDirty, 구조 변경 시 필요한 MarkArrayDirty가 정확히 호출되는지 살핀다.
  4. clear-and-rebuild를 실제 delta update로 바꾸는 방안도 비교해 본다.
  5. 제한값은 exact engine revision의 source와 console variable을 열어 직접 찾아본다.

해결 방법#

대량 변경은 여러 update로 나누며 실제로 바뀐 원소만 표시한다. gameplay상 원자적으로 보여야 한다면 client가 batch ID와 완료 표시를 받아 마지막 조각까지 임시 상태에 모아 둔다. 모든 조각을 받은 뒤 한 번에 적용한다.

초기 전체 snapshot이 일반 delta와 다르다면 chunked RPC, 별도 replicated object 또는 versioned snapshot 전송을 검토한다. 어느 방법이 맞는지는 전송량과 재전송·late join 요구사항을 먼저 측정한 뒤 정한다.

검증 방법#

  • batch 크기를 제한값 바로 아래와 위로 나눠 시험한다.
  • packet loss와 latency를 켠 dedicated server/client에서 최종 배열을 대조한다.
  • 추가, 수정, 삭제, 전체 초기화, late join은 조건별로 테스트해 본다.
  • 경고 유무만 보지 말고 server/client의 item ID와 payload checksum까지 비교한다.

주의점#

제한값을 크게 올리는 방법은 마지막에 검토한다. 전송 크기와 CPU 비용이 늘고 근본적인 dirty 처리 오류까지 숨기기 때문이다. Fast Array callback의 순서만으로 gameplay event의 정확한 전역 순서를 보장한다고 가정하면 안 된다.

참고 자료#

글 공유하기

이 글이 도움이 되셨다면 다른 사람과 공유해 주세요!

FastArraySerializer 변경·삭제 개수 제한 경고 다루기
https://hon454.github.io/posts/unreal-engine-fast-array-replication-update-limits/
작성자
Jihoon Jeon
게시일
2023-06-21
라이선스
CC BY-NC-SA 4.0
관련 게시글스마트
1
언리얼 엔진의 리플리케이션 및 RPC 순서 보장
Unreal Engine프로퍼티 복제와 OnRep, RPC의 순서 보장 범위를 살펴보고, 일시적인 상태 불일치와 액터 간 준비 순서를 처리하는 방법을 예시로 정리한다.
2
Unreal Engine PIE에서 클라이언트와 서버 값을 한 줄로 비교하기
Unreal EnginePIE에서 클라이언트 코드가 같은 프로세스의 서버 월드와 서버 측 PlayerController를 찾아 위치·속도를 한 줄로 비교하는 에디터 전용 디버그 코드와, 네트워크 에뮬레이션으로 확인한 측정 결과를 정리합니다.
3
면접 오답노트: 말하지 못한 주요 개념, Net Relevancy
Unreal Engine면접에서 제대로 답하지 못한 Net Relevancy를 다시 정리한다. AActor::IsNetRelevantFor의 판정 순서와 문서와 다른 부분, Owner가 판정을 바꾸는 방식, 연관성을 잃고 되찾을 때 RelevantTimeout과 액터 파괴, BeginPlay, OnRep, RPC에 생기는 일, ForceNetRelevant와 Replication Graph, Iris에서의 주의점, Dormancy, Priority와의 차이를 다룬다.
4
휴면 액터 깨우기: FlushNetDormancy, ForceNetUpdate, SetNetDormancy
Unreal EngineUE 5.8.3 엔진 소스 기준으로 FlushNetDormancy, ForceNetUpdate, SetNetDormancy가 각각 무엇을 바꾸는지 비교한다. 휴면 정책과 휴면 상태의 차이, ForceNetUpdate가 덤으로 하는 flush가 빠지는 조건, 값을 바꾼 뒤 깨우면 FastArray 변경이 사라지는 문제, 이를 막는 setter 패턴과 Push Model을 함께 쓸 때의 주의점을 정리한다.
5
Unreal Engine - Replication Graph
Unreal EngineUE 5.8.3 소스와 테스트 프로젝트 실측으로 Replication Graph가 기본 드라이버의 무엇을 줄이고 무엇을 줄이지 않는지 확인한다. 액터 5,000개와 클라이언트 16개까지의 측정, 효과가 있는 설정값과 이름과 반대로 동작하는 설정값, 커스텀 그래프의 라우팅과 Team Node, 5.8.3에서 재현한 버그 다섯 가지, 도입 기준과 Iris와의 관계를 다룬다.
무작위 게시글무작위

댓글

Profile Image of the Author
Jihoon Jeon
안녕하세요! 서브컬처와 자전거를 사랑하는 개발자 전지훈입니다.
공지사항
제 블로그에 오신 것을 환영합니다! 예시 공지입니다.
카테고리
태그
최신 일상
사이트 통계
게시글
73
카테고리
10
태그
143
총 단어 수
133,527
운영 일수
0일
최근 활동
0일 전
사이트 정보
빌드 플랫폼
GitHub Actions
블로그 버전
Firefly v6.16.9
라이선스
CC BY-NC-SA 4.0
목차