이전 글(링크)에 이어서 세션 플러그인 구현을 마저 진행.
세션 플러그인에서 새롭게 구현할 만들 기능은 세션 생성(CreateSession), 세션 탐색(FindSession), 세션 참여(JoinSession), 세션 시작(StartSession), 세션 파괴(DestroySession) 5가지이다.
함수를 바인딩할 델리게이트를 private 섹션에 선언
FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate;
FDelegateHandle CreateSessionCompleteDelegateHandle;
FOnFindSessionsCompleteDelegate FindSessionsCompleteDelegate;
FDelegateHandle FindSessionsCompleteDelegateHandle;
FOnJoinSessionCompleteDelegate JoinSessionCompleteDelegate;
FDelegateHandle JoinSessionCompleteDelegateHandle;
FOnDestroySessionCompleteDelegate DestroySessionCompleteDelegate;
FDelegateHandle DestroySessionCompleteDelegateHandle;
FOnStartSessionCompleteDelegate StartSessionCompleteDelegate;
FDelegateHandle StartSessionCompleteDelegateHandle;
함수를 바인딩할 수 있는 델리게이트와, 나중에 델리게이트에서 바인딩을 해제하기 위해 따로 변수에 저장하기 위한 델리게이트 핸들을 각각 하나씩 만든다.
세션 인터페이스에서 델리게이트 리스트에 델리게이트를 추가하는 기능은 FDelegateHandle
을 리턴하는데, 이를 별도의 변수로 가지고 있다가 나중에 세션 인터페이스에서 Clear
함수를 호출할 때 파라미터로 사용할 수 있다.
void OnCreateSessionComplete(FName SessionName, bool bWasSuccessful);
void OnFindSessionsComplete(bool bWasSuccessful);
void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result);
void OnDestroySessionComplete(FName SessionName, bool bWasSuccessful);
void OnStartSessionComplete(FName SessionName, bool bWasSuccessful);
델리게이트에 바인딩할 콜백 함수를 선언한다.
각각의 델리게이트가 어떠한 형태의 인풋 파라미터를 받는지는 델리게이트가 정의된 곳(OnlineSessionDelegates.h
)으로 이동해 확인할 수 있다.
예를 들어FOnCreateSessionCompleteDelegate
는 DECLARE_MULTICAST_DELEGATE_TwoParams
매크로를 사용하고 있고, FName, bool 타입 두 개의 인자를 받는 것을 확인할 수 있다. 그리고 코멘트를 보면 각각의 파라미터가 어떤 식으로 사용되는지 설명하고 있다. 이 인풋 파라미터 형식을 맞춰주지 않으면 함수를 델리게이트에 바인딩할 수 없다.
콜백 함수와 델리게이트를 바인딩하는 작업은 생성자에서 이루어진다. 생성자의 중괄호 앞에서 콜론(:) 을 붙이면 초기화 리스트를 이용한 초기화가 가능하다.
UMultiplayerSessionsSubsystem::UMultiplayerSessionsSubsystem():
CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCreateSessionComplete)),
FindSessionsCompleteDelegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnFindSessionsComplete)),
JoinSessionCompleteDelegate(FOnJoinSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnJoinSessionComplete)),
DestroySessionCompleteDelegate(FOnDestroySessionCompleteDelegate::CreateUObject(this, &ThisClass::OnDestroySessionComplete)),
StartSessionCompleteDelegate(FOnStartSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnStartSessionComplete))
{
IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get();
if (Subsystem)
{
SessionInterface = Subsystem->GetSessionInterface();
}
}
5가지 함수를 모두 생성자의 초기화 리스트에 등록하며 CreateUObject
을 사용한다.
CreateSessionCompleteDelegateHandle = SessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate);
세션 인터페이스에서 Add
를 통해 델리게이트를 바인딩하고, 이 델리게이트를 별도의 델리게이트 핸들에 저장하여 나중에 사용할 수 있게 한다.
이제 세션 인터페이스에서 CreateSession
함수를 호출할 수 있다.
이 함수는 FUniqueNetId
타입의 HostingPlayerId
, 그리고 세션의 이름, 마지막으로 FOnlineSessionSettings
타입의 NewSessionSettings
를 파라미터로 받고 있다.
FUniqueNetId
는 사용자의 고유한 id를 뜻하며, GetWorld()->GetFirstLocalPlayerFromController()
를 통해 ULocalPlayer
를 얻고 GetPreferredUniqueNetId()
함수를 통해 구할 수 있고 SessionName은 별도로 지정하거나 또는 디폴트처럼 사용할 수 있는 매크로도 존재한다. 마지막으로 FOnlineSessionSettings
타입은 어떤 설정으로 세션을 만들 것인지를 결정하는데 별도의 변수를 만들어 값을 직접 명시한 후 전달해야 한다.
나중에 다른 함수에서 세팅 값을 얻을 수 있게 하기 위해 로컬 변수로 만들지 않고 클래스 내부의 멤버 변수로 만들기로 한다.
LastSessionSettings = MakeShareable(new FOnlineSessionSettings());
LastSessionSettings->bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true : false;
LastSessionSettings->NumPublicConnections = NumPublicConnections;
LastSessionSettings->bAllowJoinInProgress = true;
LastSessionSettings->bAllowJoinViaPresence = true;
LastSessionSettings->bShouldAdvertise = true;
LastSessionSettings->bUsesPresence = true;
LastSessionSettings->Set(FName("MatchType"), MatchType, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
LastSessionSettings->BuildUniqueId = 1;
LastSessionSettings->bUseLobbiesIfAvailable = true;
bIsLANMatch
: 랜 연결을 위한 세션인지를 뜻함. 로컬 연결 뿐 아니라 모든 온라인 환경을 지원하는 플러그인이므로 false
NumPublicConnections
: 동시 연결 가능한 사용자의 수, 별도의 변수를 만들어 외부에서 전달받아 사용하도록 함bAllowJoinInProgress
: 세션 진행 도중에 난입할 수 있게 할지의 여부bAllowJoinViaPresence
: 지역(Region) 개념을 도입하는지 여부bShouldAdvertise
: 온라인 서비스에서 매치가 public하게 advertise 될 것인지 MatchType
: 키-밸류 페어 형태로 세션 세팅을 설정할 수 있고, 외부에서 전달받은 게임 모드 방식을 MatchType
이라는 키에 저장함그리고 메뉴 클래스의 호스트 버튼에 CreateButton
을 호출한다.
void UMenu::HostButtonClicked()
{
HostButton->SetIsEnabled(false);
if (MultiplayerSessionsSubsystem)
{
MultiplayerSessionsSubsystem->CreateSession(NumPublicConnections, MatchType);
}
}