일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- CS
- Gas
- STL
- Unreal
- topdownmove
- 오늘밤 세계에서 이 사랑이 사라진다 해도 #독후감 #오열
- Console
- 네트워크 기초
- 툰쉐이딩
- 코드리뷰
- build.cs
- C++
- 언리얼
- leetcode
- 브론즈
- 언리얼 엔진5 #언리얼 클라이언트 프로그래밍
- CS50
- A* Algorithm
- Toon Shading
- UE_5
- 순환 리스트
- 폭설 #미친 날씨
- 원카페#무인카페#카페추천#카페맛집
- 백준
- c++ 베이직
- Module
- 헤더 경로
- Harvard
- 메테리얼
- 언리얼엔진5 #언리얼 클라이언트 프로그래밍
- Today
- Total
WN_인생기록
[UE_5] 언리얼 멀티플레이 시스템의 이해 (Gameplay Framework+NetWork+Replication) 본문
[UE_5] 언리얼 멀티플레이 시스템의 이해 (Gameplay Framework+NetWork+Replication)
WhNi 2024. 5. 7. 18:10이제 본격적으로 네트워크에 대해서 생각해보자.
Net Mode 라고
StandAlone
DedicatedServer
ListenServer
Client
가 있다.
이걸 나누는 기준은 3가지이며,
1. 게임을 플레이 할 수 있는가?
2. 권한을 가지고 있는가?
3. 다른 플레이어가 클라로 참여하여 게임을 플레이 할 수 있는가?
라는 질문으로 모드를 나눌 수 있다.
StandAlone 은 게임 인스턴스가 로컬 플레이어를 가지고 있다.
서버에 대한 권한이 있지만 다른 플레이어가 클라로 참가할 수는 없다.
DedicatedServer는 게임 인스턴스가 있지만, 로컬플레이어가 없다. 서버 전용 콘솔 응용 프로그램으로 작동하는 즉) 서버 그 자체가 되는 것이다. 서버는 사운드, 그래픽, 사용자 입력같은 기능을 제공만 한다.
ListenServer은 게임 인스턴스가 로컬 플레이어를 가지고 있고, 서버에 대한 권한이 있고, 다른 플레이어가 클라에 참가 할 수 있다. 즉 한명의 플레이어가 호스트가 되어서 다른 플레이어를 참가하게 하는 것이다.
Client 는 게임 인스턴스가 원격 서버로 연결된다면 Client을 가지고, 로컬 플레이어를 할당받게 된다. 서버에 대한 권한은 없으며, 다른 플레이어가 클라에 참가할 수 있다.
우리의 최종 목표는 각각의 게임 인스턴스가 모두 동기화시키는 것이 제일 중요하다. 이를 위해서는
Replication 이라는 기능을 활용해야 한다.
예를 들어,
게임이 시작되면, Replication의 기능이 동작하고, 각 게임의 인스턴스는 World에 대한 복사본을 만들고 Replication 기능이 모두 동기화가 되는지 확인한다.
그래서 Replication은 NetDriver, NetConnetction, Channel 이라는 클래스가 있다.
NetDriver는 서버가 부팅되면 실행되는 클래스이고, 원격 프로세스로부터 메세지 수신을 받기 시작한다.
클라가 켜지면 클라 자체 내에서 NetDriver가 실행되고, 서버에 연결 요청을 보낸다.
서버와 클라가 연결되면 NetDriver 안에 있는 NetConnection이 설정된다.
서버는 연결된 플레이어의 수 만큼 NetConnection이 존재하고 그 안에는 Channel이 존재한다.
이 Channel은 ActorChannel이며 이 채널을 통해서 해당 액터에 대한 동기화를 진행한다.
Actor Replication
액터가 Replicate 될때, 세가지를 고려해야 한다.
1. 수명
-> 액터의 수명은 서버에서 Replicate 설정된 액터를 생성하면 클라에게 전달되어 복사본을 생성한다. 당연히 액터가 서버에서 소멸되면 클라에서도 소멸된다.
2. 속성
-> 액터에서 지정된 속성이 있는경우, 해당 속성이 서버에서 변경되면 클라도 변경된다.
UPROPERTY(Replicated)
FName playerName;
Property Replication
해당 속성 UPROPERTY에 Replicated를 추가하면 된다.
이것과 따라오는 개념이 GetLifetimeReplicatedProps()라는 함수를 정의해야 하는데, Net/UnrealNetwork.h를 추가해서 정의해야 한다. 이는 복제해야 하는 property와 그 조건을 저장한다. 해당하는 클래스와, property를 DOREPLIFETIME이라는 매크로로 저장할 수 있다.
void AMyGameState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMyGameState, playerName);
}
3. RPC
-> 서버와 클라간의 메세지를 주고받는 시스템이며, 3가지가 있다.
3-1 Clinet: 서버에서 호출되지만 클라에서 실행되는 RPC
UFUNCTION(Client)
void Client_Send();
--> 서버에서 이런식의 코드가 실행되면
void Client_Send_Implementation()
{
//Execute in client
}
--->클라에서 "_Implementation"이라는 접미사가 붙게되고, 여기에 해당하는 코드가 실행된다.
Ex) 플레이어별 State, Inventory, 개인메세지, 퀘스트업데이트, 업적 , 개인 UI,
3-2 Server: 클라에서 호출되지만 서버에서 실행되는 RPC (클라에서 데이터를 서버에게 보내는것)
UFUNCTION(Server)
void Server_Send();
--> 클라에서 이런식의 코드가 실행되면
void Server_Send_Implementation()
{
if(HasAuthority())
{
//Execute in Server
}
}
--->서버에서 "_Implementation"이라는 접미사가 붙게되고, 여기에 해당하는 코드가 실행된다.
---> 서버는 WithValidation으로 선언될 수 있는데, 서버가 클라에서 보내는 값을 신뢰할 수 있는지 확인하는 _Validate를 사용해서 이 검사에 실패하면 해당 클라에 데이터를 원래대로 돌려놓는다.
Ex) 무기 발사, 특정 위치로 스폰, 서버에서 확인해야 하는 아이템 픽업, 데미지 처리, 능력 활성화
3-3 Multicast: 서버에서 호출되고 서버 포함 연결된 모든 클라에서 실행되는 RPC
(실행될때만 Replicate 된다.)
UFUNCTION(NetMulticast)
void Multicast_Send();
--> 서버에서 이런식의 코드가 실행되면
void Multicast_Send_Implementation()
{
//Execute in Server and Client
}
--->서버, 클라에서 "_Implementation"이라는 접미사가 붙게되고, 여기에 해당하는 코드가 실행된다.
Ex) 글로벌 이벤트, 라운드 시작, 종료, 퀘스트 시작, 트리거 효과, 날씨, 점수
또한 RPC는 신뢰성이라는 기능이 있는데,
UFUNCTION(Client, Reliable)
UFUNCTION(Client,UnReliable)
Replicate하는 과정속에서, 대역폭이라는게 존재하는데, 일반 게임의 FPS 같은 거라고 생각하면 된다. 너무 로드 되는게 많으면 대역폭이 과부화가 걸려서 데이터가 제대로 전달이 안될수가 있다. 그래서 휘발성 데이터 혹은 중요 하지 않은 데이터는 UnReliable 설정을 하게 되면 대역폭이 과부화된 경우 삭제될 수가 있는 것이다. 그러나 중요한 체력, 스코어 등의 데이터를 Reliable로 설정하면 호출된 순서로 데이터가 전송되는 것이다.
액터에 replicate를 설정하려면, bReplicates=true를 해주기만 하면 된다. 그리고 Replcate 하기 위한 NetConnetion에서 ActorChannel를 설정하는 것이다.
Replicate는 서버가 해당 액터와 관련된 클라에 업데이트를 보내는 빈도를 결정하는데
NetUpdateFrequency / NetPriority를 통해서 그 빈도를 정할 수 있다.
Ownership
모든 액터는 소유자로 지정된 다른 액터를 가질 수 있다. 예를들어, NetConnection을 통해 플레이어가 로그인을 하게 되면, NetConnection을 소유하고 있는 PlayerController를 할당 받게 된다. 이때 PlayerController를 소유하고 있는 State나 다른 액터를 소유할 수 있게 되는 것이다.
이 개념은 Authority와는 다른데,
Authority
Authority는 항상 서버가 가지고 있다. 클라는 업데이트를 받는 것이기 때문에 액터에 대한 권한이 나에게 있는지 잘 확인해야 한다.
NetRole 에서는 4가지가 분류되는데
ROLE_None
ROLE_SimulatedProxy
ROLE_AutonomousProxy
ROLE_Authority
이 표 처럼 정리 될 수 있다.
AutonomousProxy는 완전한 권한은 없지만, 액터의 움직임과 행동은 제어한다는 것이다.
SimulatedProxy 는다른 네트워크 플레이어나 서버에 의해 제어되는 액터를 클라이언트에서 시뮬레이션하기 위해 사용한다.
중요한 팁은, GetLocalRole() == ROLE_Authority() 나 HasAuthority를 했을때,
true면 Dedicated 서버 혹은 ListenServer라는 것이고
false면 Client라는 것이다.
출처
https://www.youtube.com/watch?v=JOJP0CvpB8w&t=182s
'언리얼 개발 > 탐구(이론)' 카테고리의 다른 글
[UE_5] AI (0) | 2024.05.14 |
---|---|
[UE_5] 언리얼 멀티플레이 시스템의 이해 (Replication Mode) (0) | 2024.05.09 |
언리얼 멀티플레이 시스템의 이해 (Gameplay Framework) (0) | 2024.05.07 |
[UE_5] GAS란 무엇인가 - Gameplay Cues (0) | 2024.04.24 |
[UE_5] GAS란 무엇인가 - Gameplay Effects (0) | 2024.04.24 |