네트워크 게임에서 엔티티 ID를 어떻게 강력하게 할당 할 수 있습니까?


17

네트워크 게임을 위해 엔터티 시스템을 작업 중이며 엔터티 및 엔터티 자체에 대한 참조를 직렬화하는 데 사용할 수있는 고유 한 32 비트 정수 ID를 각 엔터티에 할당하고 있습니다.

현재 엔티티가 생성 될 때마다 카운터를 늘리고 있습니다. 나는 ID가 결국 없어 질 것이라고 생각하지만 실제로 40 억 엔터티가있을 것으로 기대하지는 않습니다. 또한 엔티티 # 5가 파괴되고 ID가 5 인 경우 문제를 피할 수 있습니다. 새로운 # 5 또는 기존의 삭제 된 # 5를 의미합니까?

문제는 충돌을 처리 / 피하는 방법을 잘 모르겠다는 것입니다. 현재 클라이언트가 현재 "무료 ID"보다 높은 ID를 가진 엔터티에 대한 업데이트를 수신하는 경우 해당 ID를 초과하는 무료 ID와 충돌합니다. 그러나 그다지 강력하지는 않습니다.

나는 각 클라이언트에 범위를 할당하여 충돌없이 엔티티를 할당 할 수 있다고 생각했지만 (상위 n 비트는 플레이어 번호입니다) 시간이 지남에 따라 범위가 겹치기 시작하면 어떻게 될지 걱정됩니다.

이것을 처리하는 더 좋은 방법이 있습니까? ID가 넘치거나 허용 범위의 끝을 지날 때조차 신경 써야합니까? 이러한 경우를 감지하는 코드를 추가 할 수 있지만 충돌 이외의 상황에서 발생하면 어떻게됩니까?

또 다른 옵션은 128 비트 GUID와 같이 고유 할 가능성이 더 높은 것을 사용하는 것이지만 네트워크 트래픽을 최소화하려는 게임에는 실제로는 매우 무거운 것 같습니다. 또한 현실적으로 한 번에 더 많은 엔터티가 필요하지 않으며 32 비트 또는 24 비트 정수에 적합합니다.

감사!


1
모든 클라이언트에 동일한 엔터티가없는 이유는 무엇입니까? 클라이언트가 동기화되지 않습니까? 또는 클라이언트가 모두 같은 게임을 실행하지 않는 거대한 세상입니까?
Philip Philip

2
지금까지 내 아키텍처는 UE3 아키텍처를 느슨하게 따릅니다 (자세한 내용은 여기 참조 ). 기본적으로 고객은 전 세계에있는 엔티티에 대해서만 알고 있습니다. 또한 클라이언트는 잠금 단계로 실행되지 않지만 서버는 대부분의 논리를 제어하고 언제든지 클라이언트 데이터를 덮어 쓸 수 있습니다. 나는 그것에 대해 생각하기 때문에 서버가 엔티티를 생성하고 클라이언트가 RPC를 사용하여이를 수행하게 할 수 있다고 생각합니다. 최선의 방법을 모르겠습니다. 나는 날마다 그래픽 프로그래머입니다 :)
Lucas

1
나는 당신이 말했듯이 서버가 주어진 아키텍처 내에서 가능하다면 서버에 의해서만 처리되어야한다고 생각합니다. 그런 다음 엔티티 목록 / 맵과 별도로 존재하는 무료 엔티티 ID 스택을 유지하여 사용 가능한 ID를 알 수 있습니다. 신뢰할 수있는 서버 모델에 실패하면 범위에 따라 원거리 접근 방식이 제대로 작동합니다. 40 억은 MMO에서 4000 명의 플레이어들 사이에서 나눌 수있는 수준입니다. 그런 다음 인증 방식과 동일한 방법으로 사용 가능한 ID를 추적하십시오. 섬기는 사람.
엔지니어

@Lucas, 귀하의 링크는 "서버가 각 클라이언트에 대한"관련 "액터 세트를 식별합니다"라고 말합니다. 이는 서버가 모든 엔티티에 대해 알고 있으며이를 열거 할 수있는 위치에 있음을 의미합니다.
Kylotan

1
그러나 클라이언트가 새 엔티티 A를 작성하지만 작성 메시지를 수신하기 전에 서버가 새 엔티티 B를 작성하는 경우 모두 동일한 "무료"ID가 지정됩니다.
Lucas

답변:


13

내가 한 일은 서버가 모든 것을하게하는 것이다. 클라이언트는 단순히 서버에게 무언가를하도록 요구할 수는 있지만 스스로 할 수는 없습니다. 이 경우 서버는 항상 ID를 할당하고 문제를 해결하는 서버입니다.

서버가 "로켓을 쏴라"또는 "여기에서 태양 광 발전소 만들기"와 같은 작업을 승인 할 때까지 클라이언트 측 예측을 다루지 않았습니다. 이러한 조치는 엔티티를 작성하려고하며 엔티티에는 ID가 있습니다. 지금까지 서버를 기다리는 엄지 손가락에 앉아 있지만 서버 승인을 기다리는 동안 임시 엔티티를 작성해야한다고 생각합니다. 서버 승인을 받으면 서버가 ID를 할당하고 임시 개체를 업데이트하거나 덮어 쓸 수 있습니다.

또한 ID 오버플로를 처리하지 않았지만 서버가 모든 권한을 가지고 오버플로를 감지하면 필요한 것으로 간주하는 모든 처리 (0에서 다시 시작, 무료 스택에서 선택, 충돌 등) 및 모든 작업을 수행 할 수 있습니다 고객은 심지어 알지도 모릅니다. 클라이언트는 서버가 전달한 ID 만 수락합니다.


좋은 정보를 주셔서 감사합니다! 서버로 모든 엔티티 접근 방식을 작성했지만 결국 대기 시간이 너무 길면 Trevor의 방법을 시도합니다.
Lucas

클라이언트 특정 ID (서버를 기다리는 동안 예측 필요)의 경우 ID에 접두사를 사용할 수 있습니다.
danijar

6

상업용 멀티 플레이어 게임에서이 작업을 수행 할 때 정확히 제안했습니다. 32 비트 GUID 정수를 사용하십시오. 여기서 상위 8 비트는 플레이어 번호이고 하위 24 비트는 로컬로 고유 한 숫자를 포함합니다.

로컬 번호가 오버플로되면 (내 경우에는 거의 발생하지 않을 것입니다. 정상적인 사용시 단일 네트워크 세션에서 4 ~ 5 일 동안 연속 재생 시간이 발생하여 발생했을 경우) 소유자는 "내 개체를 모두 재설정합니다"라는 메시지가 나타나고 0부터 시작하여 존재하는 모든 개체의 번호를 다시 매 깁니다. 이 메시지는 모든 피어에게 수신 한 개체를 삭제하고 다시 쿼리하도록 지시했습니다.

보다 현명한 접근 방식은 모든 기존 객체에 대해 "GUID가 'n'인 객체는 이제 GUID가 'm'인 객체"라는 메시지입니다. 그러나 제 경우에는 실제로 일어날 가능성이 거의 없었으며, 단일 네트워크 세션에서 5 일 동안 논스톱 플레이를 한 후 사람들이 0.5 초 동안 세상에서 사라지는 원격 객체를 정말로 염려하지 않을 것이라고 생각했습니다. ;)


오버플로를 처리하는 것이 좋습니다. 간단하지만 생각하지 못했습니다 :). 클라이언트가 게임에 참여할 때 사용하는 것과 동일한 코드 경로를 기본적으로 재사용 할 수 있기 때문에 모든 엔티티를 "잊어 버린다"
Lucas

4

고객이 자신의 엔티티를 생성 할 수 있다면 피어 투 피어 멀티 플레이어 게임이 있다고 생각합니다.

이 경우 클라이언트가 너무 많지 않을 수 있습니다. 분명히 256 개를 넘지 않아야합니다. 그리고 엔티티 ID는 24 비트 (16000000+ 엔티티는 모두에게 충분합니다)에 맞도록 보장됩니다. 따라서 ID의 최상위 바이트를 클라이언트의 ID와 동일하게 만드십시오.

entityId = clientId<<24 + (maxEntityIn++)

또는 뭔가.

그리고 내가 틀렸고 권위있는 서버가 있다면 클라이언트에 새로운 엔티티를 만들지 마십시오 .


1

영구 멀티 플레이어 게임에서 '가장 순진한'방법 (새 ID마다 정수만 증가)을 사용하고 있으며 클라이언트가 새 ID를 만들지 못하므로 제대로 작동합니다.

클라이언트가 설명 된 일종의 GUID 기술을 사용하여 결정하도록 허용하면 클라이언트는 Old ID를 새 항목에 할당하여 다양한 버그를 도입 할 수 있습니다 (즉, 5 초처럼 생각하는 내 머리 위에 생각한 것입니다) 다른 허점이있을 수 있습니다).

일반적으로 부정 행위를 방지하기 위해 서버는 모든 생성 및 유효성 검사를 수행해야 합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.