[UE_5] Online Subsystem
멀티플레이를 하기 위해서는 Online Subsystem이 있어야 한다.
Subsystem은 언리얼 엔진 모듈중 하나로써 멀티플레이를 가능해주는 서비스를 지원한다.
플랫폼은 스팀, PSN, XboxLive 를 지원한다.
가장 먼저, 해당 플랫폼에 맞는 플러그인을 프로젝트에 추가하여 활성화 시킨다.
이후에,
프로젝트의 Config 파일에 DefaultEngine.ini 를 수정해야 한다.
[/Script/Engine.GameEngine]
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
[OnlineSubsystem]
DefaultPlatformService=NULL
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
; If using Sessions
bInitServerOnClient=true
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"
여기서
[OnlineSubsystem]
DefaultPlatformService=NULL 이 부분은 현재 NULL 이지만
필요한 플랫폼이 있다면 Steam이나 다른 플랫폼으로 수정하면 된다.
이후에는 GameInstanceSubsystem class를 하나 생성하고
void Initialize(FSubsystemCollectionBase& Collection) override;
void Deinitialize() override;
생성자와 소멸자를 만들어준다.
여기서
IOnlineSubsystem* OnlineSubsytem =IOnlineSubsystem::Get();
#include "OnlineSubsystem.h"를 추가하고
IOnlineSubsystem 클래스를 가져오면 된다.
OnlineSubsytem을 다루는건 대부분
IOnlineSessionPtr SessionInterface;
#include "Interfaces/OnlineSessionInterface.h"를 추가하고
사용하는 IOnlineSessionPtr의 세션 인터페이스이다.
Session Interface의 기능은 멀티플레이에서 중요한 패킷을 보내고 돌아올때 콜백하는 델리게이트 기능들이 대부분이며, 매치 메이킹, 세션 생성, 세션 찾기, 세션 참가 등의 기능을 가지고 있다.
그 안에 세션을 설정하는 다른 포인터가 있는데,
FOnlineSessionSettings SessionSettings;
#include "OnlineSessionSettings.h" 를 추가하고 사용하는 FOnlineSessionSettings가 있다.
SessionSettings.bAllowJoinInProgress = true;
SessionSettings.bIsDedicated = false;
SessionSettings.bShouldAdvertise = true;
SessionSettings.NumPublicConnections = 2;
SessionSettings.bUseLobbiesIfAvailable = true;
SessionSettings.bUsesPresence = true;
SessionSettings.bAllowJoinViaPresence = true;
같이 세션에 대한 설정을 직접적으로 할 수 있다.
//DefaultEngine.ini ->[OnlineSubsystem] ->DefaultPlatformService=Steam
bool IsLan = false;
if (IOnlineSubsystem::Get()->GetSubsystemName() == "NULL")
{
// DefaultEngine.ini ->[OnlineSubsystem] ->DefaultPlatformService=NULL
IsLan = true;
}
SessionSettings.bIsLANMatch = IsLan;
SessionSettings.Set(FName("SERVER_NAME"),ServerName,EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
SessionInterface->CreateSession(0, MySessionName, SessionSettings);
Create 세션을 통해서 세션 이름, 세팅, 호스팅 숫자까지 조절도 가능하다.
Find Server는
if (ServerName.IsEmpty())
{
PrintString("Server name cannot be empty!");
ServerJoinDelegates.Broadcast(false);
return;
}
SessionSearch = MakeShareable(new FOnlineSessionSearch());
bool IsLAN = false;
// DefaultEngine.ini ->[OnlineSubsystem] ->DefaultPlatformService=NULL
if (IOnlineSubsystem::Get()->GetSubsystemName() == "NULL")
{
IsLAN = true;
}
// 랜에서 탐색
SessionSearch->bIsLanQuery = IsLAN;
// 랜에서 탐색할 수 있는 최대 세션 갯수
SessionSearch->MaxSearchResults = 9999;
SessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);
ServerNameToFind = ServerName;
SessionInterface->FindSessions(0, SessionSearch.ToSharedRef());
이런식으로 Session Search 라는 FOnlineSessionSearch 이 있어서 이를 통해 생성된 세션을 찾을 수 있다.
SessionInterface의 기능은 대부분 델리게이트 인데,
UFUNCTION(BlueprintCallable)
void CreateServer(FString ServerName);
UFUNCTION(BlueprintCallable)
void JoinServer(FString ServerName);
이렇게 CreateSession 혹은 JoinSession을 했을때, 패킷을 주고 받아올때, 어떤 로직을 해야하는지 정해야 하는게 델리게이트이다. 그래서 만약 Session을 생성했을때, 생성이 완료된 시점 ->에 델리게이트가 발동하게 되는데 이를 이용하여
void OnCreateSessionComplete(FName SessionName, bool WasSuccessful);
void OnDestroySessionComplete(FName SessionName, bool WasSuccessful);
void OnFindSessionComplete(bool WasSuccessful);
void OnJoinSessionComplete(FName SessionName,EOnJoinSessionCompleteResult::Type Result);
이와 같은 콜백 함수들을 생성할 수 있고, 이에 대한 델리게이트 설정은 Initialize에서 하면 된다.
if (SessionInterface.IsValid())
{
// 세션이 생성되면 완료가 되었다고 리스폰 해주는 델리게이트
SessionInterface->OnCreateSessionCompleteDelegates.AddUObject(this, &UMultiplayerSessionSubsystem::OnCreateSessionComplete);
// 세션이 파괴되면 완료가 되었다고 리스폰 해주는 델리게이트
SessionInterface->OnDestroySessionCompleteDelegates.AddUObject(this, &UMultiplayerSessionSubsystem::OnDestroySessionComplete);
// 세션을 찾으면 리스폰 해주는 델리게이트
SessionInterface->OnFindSessionsCompleteDelegates.AddUObject(this, &UMultiplayerSessionSubsystem::OnFindSessionComplete);
// 세션 참가되면 리스폰 해주는 델리게이트
SessionInterface->OnJoinSessionCompleteDelegates.AddUObject(this, &UMultiplayerSessionSubsystem::OnJoinSessionComplete);
}
이렇게 Online Subsystem을 이용해서 세션을 생성하고, 참가할 수 있다.