Unreal NetMode, NetConnection, NetDriver
Unreal의 네트워크 구조 이해를 위해 필요한 것들
NetMode, NetDriver, NetConnection, NetRole 등의 구조를 이해해야
Dedicated Server 기반의 게임 제작하는데 문제가 없다
기본 개념 정리
NetMode → 이 클라이언트/서버 프로그램이 어떤 상태인가? (Dedicated? Client?)
NetRole → 이 Actor가 현재 어떤 권한(Role)을 가지고 있는가?
NetDriver → 실제 네트워크를 관리하는 엔진의 드라이버(네트워크 백엔드)
NetConnection → 한 클라이언트와 서버 사이의 실제 연결 객체
NetMode
현재 프로세스의 네트워크 모드를 뜻함
우리가 작성중인 로직이 ‘서버’에서 도는지 ‘클라’에서 도는지를 분류하기 위해
필요한 개념!
- 멀티 플레이에선 ‘같은 코드’가 여러 PC에서 동작하며
이를 위하여 각 PC의 역할 구분이 필요함
NetMode의 종류
| NetMode | 의미 |
|---|---|
| NM_Standalone | 싱글플레이 or 로컬 플레이 |
| NM_ListenServer | Listen Server (서버+호스트 플레이어가 같이 있음). |
| NM_DedicatedServer | Dedicated Server (호스트 없는 순수 서버). |
| NM_Client | 네트워크 클라이언트. |
-
- StandAlone
- 원격 클라 연결을 허용하지 않는 서버
(싱글 or 로컬 플레이 게임에 주로 사용)
- StandAlone
-
- Client
- 게임이 네트워크 멀티 플레이 세션에서 ‘클라이언트’로 실행됨
서버측 로직 실행 x, 서버로부터 복제된 proxy를 보여줌
- Client
-
- Listen Server
- 원격 클라이언트의 연결 수락하고, 자신의 로컬 플레이어도 서버에 배치
서버 프로세스도 게임에 참여함
캐주얼 협동 같은 멀티 플레이어에 자주 사용
- Listen Server
-
- Dedicated Server
- 원격 클라이언트의 연결을 허용하나, 자신의 로컬 플레이어는 x
그래픽, 사운드, 입력 및 기타 플레이어 위주의 기능을 삭제한 방식
지속적이고 안전한 대규모 멀티 플레이 게임에 사용
- Dedicated Server
NetMode에 따른 액터 위치
-
- 서버에만 존재하는 Actor
- GameMode
- 클라에서 GetGameMode() 함수 호출시 Nullptr 반환이 됨
- 서버에만 존재하는 Actor
-
- 서버 + 모든 클라에 존재하는 액터
- 배경용 Actor와 Pawn
- 서버 + 모든 클라에 존재하는 액터
-
- 서버와 클라에만 존재하는 액터
- Player Controller, ABP
- ABP는 동작 종료 등을 체크할 때, 사용할 수 있음
- 서버와 클라에만 존재하는 액터
-
- 클라에만 존재하는 오브젝트들
- UI 등 렌더링에 필요한 요소들
- 클라에만 존재하는 오브젝트들
예시 코드
ENetMode Mode = GetWorld()->GetNetMode();
이 외에도
IsDedicatedServer 와 같은 다양한 함수가 존재
NetDriver
언리얼의 네트워크 엔진 (소켓, 전송 기능)
네트워크 연결을 실제로 관리하는 백엔드 드라이버
- 언리얼 네트워크 통신에서 로우레벨 동작을 관리하는 클래스
- 싱글 플레이에선
UNetDriver객체 생성 x - 멀티 플레이에서만
UWorld::Listen()함수를 통해UNetDriver객체가 생성 - 각 PC마다
UNetDriver객체 생성
World
└── NetDriver
├── ServerConnection (서버에서만)
└── ClientConnections[] (클라이언트 목록)
NetDriver의 종류
| NetDriver | 용도 |
|---|---|
| GameNetDriver | 게임 멀티플레이를 위한 기본 드라이버 |
| IpNetDriver | IP 기반의 네트워크 TCP/UDP 담당 |
| DemoNetDriver | 리플레이/데모 재생용 |
| PendingNetDriver | 접속 시도 중인 네트워크 |
NetConnection
클라이언트와 서버의 1:1 연결
서버는 여러 ClientConnections 를 가짐
클라는 하나의 ServerConnection만 가짐
- 다른 PC와의 연결이 발생하면
UNetConnection객체가 생성 - 서버에 클라이언트가 접속하면 서버에
ClientConnection객체 추가
- 반대로 클라엔
ServerConnection객체 생성
- 반대로 클라엔
- 클라 <-> 서버는
UNetConnection객체를 통해 통신함 UNetDriver는 생성된UNetConnection객체를 소유, 관리-
서버 PC에 생성된
UNetDriver는 접속한 클라이언트의 수만큼 관리하게 됨 - 클라 PC의 UNetDriver는 ServerConnection 하나만을 관리함
용어 정리
- ServerConnection : 클라이언트가 소유한 UNetConnection 객체
- ClientConnection : 서버가 소유한 UNetConnection 객체
결국 UNetConnection을 관리하며
객체의 ‘네이밍’을 저렇게 한 것임
즉,
클라쪽의 상황
UWorld
└── GameNetDriver (UNetDriver)
└── ServerConnection : UNetConnection *
서버 쪽의 상황
UWorld
└── GameNetDriver (UNetDriver)
├── ClientConnections[] : TArray<UNetConnection*>
│ [0] → 플레이어1
│ [1] → 플레이어2
│ [2] → 플레이어3
└── ServerConnection = nullptr
NetRole
이 Actor가 이 머신(서버/클라이언트)에서 어떤 권한을 가졌는가?
- Actor의 권한 상태(Role)을 나타내는 개념
- Actor의 진짜 주인에 대한 이야기이기도 하다
- Actor의 진짜 주인에 대한 이야기이기도 하다
예시를 들자면)
이 Actor의 주인은 Server,
이 Actor는 서버의 복제를 받아 움직이는 상황,
이 Actor는 클라이언트가 입력을 할 수 있는 Actor이다 등
-> 이 Actor의 ‘권한’은 누구에게 있는지를 표현하는 개념
NetRole의 2가지 Role
-
- LocalRole
- 현재 머신(서버/클라)에서의 Actor 권한
- 서버는 기본적으로 모든 Actor에 대하여 ‘절대 권한’을 가지는 편
- 클라에선 각 Actor의 역할이 크게 바뀌는 편이다
- 플레이어 조종 캐릭터 : ROLE_AutonomousProxy
- 다른 사람의 조종 캐릭터 : ROLE_SimulatedProxy
- 플레이어 조종 캐릭터 : ROLE_AutonomousProxy
- LocalRole
-
- RemoteRole
- 현재 반대편의 네트워크 구조에서의 Actor의 권한
(클라 -> 서버 / 서버 -> 클라)
- RemoteRole
-
- RemoteRole이 필요한 이유??
- LocalRole만 존재하였다면 ‘분간’하기 어려운 케이스를 고려한 것
- 예를 들자면, ‘서버’에서 Spawn한 NPC 캐릭터와 접속한 플레이어의 LocalRole은 모두 Authority임
‘구분’하기 힘든 상태 - 그러나 RemoteRole을 통하여 ‘
ROLE_AutonomousProxy‘인 캐릭터를 찾는다면
플레이어 캐릭터를 구분할 수 있음
- RemoteRole이 필요한 이유??
NetRole의 종류
| Role | 의미 | 사용처 |
|---|---|---|
| ROLE_Authority | 서버에서만 가지는 절대 권한 | 게임의 실제 상태 변경 |
| ROLE_AutonomousProxy | 클라이언트가 주도적으로 조작하는 Actor | PlayerController, 본인 캐릭터 |
| ROLE_SimulatedProxy | 서버의 복제를 “수동으로 따라가는” Actor | 다른 플레이어의 캐릭터 |
| ROLE_None | 레플리케이션 되지 않는 Actor | 다른 네트워크에서 안보이는 용도(드문 편) |
ex)
서버에 A,B,C가 존재할때의 NetRole 예시
| Actor | LocalRole | RemoteRole |
|---|---|---|
| A(내 캐릭터) | AutonomousProxy | Authority |
| B(타인) | SimulatedProxy | Authority |
| C(타인) | SimulatedProxy | Authority |
- AutonomousProxy의 존재를 통해 해당 클라이언트에서
‘입력’을 처리한 후, 서버에 RPC 요청을 할 수 있음
- 서버와 클라 모두 이동 처리를 진행하여 ‘부드럽게’ 보일 수 있음
- 네트워크 지연(Latency)를 최소화하는 방식
- 서버와 클라 모두 이동 처리를 진행하여 ‘부드럽게’ 보일 수 있음
- AutonomousProxy는 ‘입력’으로 조종되는 단 하나의 Pawn 정도에만 쓰임
- 플레이어가 대규모 RTS 등을 통해 유닛을 대량으로 조정하는 경우도
‘그 입력’을 받아 서버에서 처리 후, 클라에 동기화 하는 것임
- 플레이어가 대규모 RTS 등을 통해 유닛을 대량으로 조정하는 경우도
- ROLE_None 같은 경우는 사용처가 꽤 드문 편
간혹 ‘서버’에서만 사용하는 Actor에서 고려할 수 있음
사용 방식
FORCEINLINE_DEBUGGABLE bool AActor::HasAuthority() const
{
return (GetLocalRole() == ROLE_Authority);
}
-
게임에 중대한 영향을 끼치는 Damage/Spawn 같은 기능이라면
서버에서만 처리되도록 해당 함수를 통해 ‘서버’ 확인 -
입력/UI 로직의 경우는
ROLE_AutonomousProxy에서만 실행되어야 하니
AController::IsLocalController()나APawn::IsLocallyControlled()를 이용
OwnerShip
- 하나의
ClientConnection은 하나의PlayerContoller를 소유 - 즉,
PlayerContoller의 Owning Connection은ClientConnection PlayerController가 빙의하는 폰의Owner속성은 해당 플레이어 컨트롤러로 설정됨- 폰에 무기 Actor가 생성되고, 무기 액터의 Owner 속성에 해당 폰을 설정할 수 있음
- ClientConnection ~ 무기 Actor 까지의 소유 관계를 ‘패밀리’ 라고도 부름
-
소유 관계 속에 있는 액터가 ‘본인’의 Owning Connection을 얻으려면
AActor::GetNetConnection()호출 - 이러한 소유 관계가
RPC와 Property Replication 과 연관됨
- OwnerShip에 대한 추가적인 내용은 해당 개념들을 포스팅할때 더 다룰 예정
- OwnerShip에 대한 추가적인 내용은 해당 개념들을 포스팅할때 더 다룰 예정
댓글남기기