WN_인생기록

[UE_5] Online Subsystem 본문

언리얼 개발/탐구(이론)

[UE_5] Online Subsystem

WhNi 2024. 5. 16. 21:00

멀티플레이를 하기 위해서는 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을 이용해서 세션을 생성하고, 참가할 수 있다.