원격 액터 초기화 과정
게임과 무관한 액터 설정의 초기화는 PostInitalizeComponents에서 진행
게임 진행에 필요한 초기화는 BeginPlay
실제 게임이 시작되기 전, 월드의 모든 액터들이 생성되고 초기화된 상태에서 다른 액터들과의 상호작용이 필요한 게임플레이 관련 초기화에 적합
PostInitializeComponents는 액터를 설정하는 기능이라 네트워크와는 관련이 없으므로 언리얼 엔진에서 원격 액터 세팅이 모두 마무리될 때 PostNetInit 함수가 호출됨
PreLogin에서 ErorrMessage를 설정하면 클라이언트 접속이 거부당하고 클라이언트는 StandAlone으로 독립적으로 동작함
void AABGameMode::PreLogin(const FString& Options, const FString& Address, const FUniqueNetIdRepl& UniqueId, FString& ErrorMessage)
{
Super::PreLogin(Options, Address, UniqueId, ErrorMessage);
ErrorMessage = TEXT("Server Is Full");
}
언리얼 엔진에서의 커넥션 구성
네트워크 통신을 담당하는 주요 클래스
PlayerController
네트워크 통신에 접근 가능한 게임 내 대표 액터
네트워크 관련된 작업을 지시할 필요는 없고 소유권 관리만 하면 됨
UNetConnection
주고받는 패킷 데이터의 인코딩/디코딩, 네트워크 통신량 조절, 채널 관리
UNetDriver
로우 레벨에서의 소켓 관리와 패킷 처리, 네트워크 통신 설정
서버의 네트워크 초기화 과정
UWorld::InternalGetNetMode() : 현재 월드에 NetDriver가 있으면 클라이언트-서버, 없으면 StandAlone으로 판단
서버는 UWorld::Listen() 함수를 호출해 NetDriver를 생성하여 네트워크 기능을 시작
NetDriver의 커넥션 관리
NetDriver는 다수의 커넥션을 관리하고 있으며, 서버와 클라이언트에 따라 다르게 동작함
클라이언트의 NetDriver는 항상 하나의 서버 커넥션을 가짐
서버의 NetDriver는 다수의 클라이언트 커넥션을 가짐
커넥션과 오너십
Connection : 데이터를 전달하는 네트워크 통로
Packet : 네트워크를 통해 전달되는 데이터 단위
Channel : 언리얼 엔진 아키텍쳐에 따라 구분된 데이터를 전달하는 논리적인 통로, 용도에 따라 데이터를 구분하는 접속 단위, 하나의 커넥션에 다수의 채널을 가질 수 있음
Bunch : 언리얼 엔진의 아키텍쳐에 사용되는 데이터, 채널에서 용도에 맞게 정리된 데이터 묶음
데이터 통신을 관리하기 위한 대표 액터로 플레이어 컨트롤러가 주로 사용되므로 서버는 여러 개의 플레이어 컨트롤러, 클라이언트는 하나의 플레이어 컨트롤러가 생성됨
커넥션을 담당하는 대표 액터는 커넥션에 대한 오너십을 가진다고 표현함
플레이어 컨트롤러를 제외한 컨텐츠 액터가 커넥션에 소유됐는지 확인하기 위해 Owner가 플레이어 컨트롤러인 경우에 해당 액터도 플레이어를 소유하는 동일한 커넥션에 소유된 것
예로, 폰이 빙의(Possess)되면 폰의 Owner가 컨트롤러로 설정되어 자동으로 커넥션에 소유되고 더 이상 빙의되지 않으면 커넥션에 소유되지 않음
클라이언트 폰은 빙의되지 않고 프로퍼티 리플리케이션에 의해 Owner(PlayerController)가 동기화됨
또 다른 예로, 폰에 소유된 인벤토리 아이템 오브젝트도 동일한 커넥션에 소유됨
컴포넌트는 소유한 액터 혹은 폰이 커넥션에 소유됐는지 확인해야 함
RPC를 호출할 때 커넥션 소유권이 있어야 하고 커넥션 소유권에 따라 클라이언트가 결정됨
액터 리플리케이션은 커넥션 연관성 때문에 커넥션 소유권을 가진 액터만 동기화 가능
프로퍼티 리플리케이션도 모든 프로퍼티를 보내는 것이 아닌 커넥션 소유권을 가진 액터의 프로퍼티만 전달할 수 있음
따라서 이러한 옵션들로 네트워크 데이터의 양을 최적화할 수 있음
클라이언트에서 오너를 지정해도 클라이언트의 플레이어 컨트롤러는 오너십이 없기 때문에 오너십 설정이 안됨
따라서 서버에서 오너를 설정해야 함
if(!HasAuthority)
{
SetOwner(GetWorld()->GetFirstPlayerController());
}
// 서버에서 오너 설정
for(FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator)
{
APlayerController* PlayerController = Iterator->Get();
if(PlayerController && !PlayerController->IsLocalController()) // 서버에서 클라이언트 플레이어 컨트롤러는 로컬이 아님
{
SetOwner(PlayerController);
break;
}
}
액터와 플레이어 컨트롤러의 NetConnection
어떤 액터가 통신하기 위해서는 자신을 소유한 액터가 커넥션을 소유해야 함
일반적으로 플레이어 컨트롤러는 NetConnection을 소유하고 있고, NetConnection은 자신을 소유한 플레이어 컨트롤러의 정보를 가짐
'언리얼 > 네트워크 멀티플레이 프레임워크' 카테고리의 다른 글
언리얼5 RPC (0) | 2025.01.13 |
---|---|
언리얼5 액터 리플리케이션 (0) | 2025.01.10 |
언리얼5 액터의 역할과 Connection HandShaking (0) | 2025.01.08 |
언리얼5 네트워크 모드와 로그인 (0) | 2025.01.01 |
언리얼 네트워크 멀티플레이 프레임워크 개요 (1) | 2024.12.31 |