๊ฐ์
์ง๋๋ฒ์ Online Subsystem Steam์ ํ์ฉํ์ฌ Steam์ Session์ ์์ฑํ์๋ค. ๋งํฌ
์ด๋ฒ์ ๋ค๋ฅธ PC๋ก ์์ฑ๋ Session์ ์ฐพ๊ณ ์ฌ๊ธฐ์ ์ฐธ๊ฐํด๋ณด๊ฒ ๋ค.
{ Session Find And Join }
๊ณผ์
(1) JoinGameSession()์์ session์ ์ฐพ๋๋ค.
(2) session ์ฐพ๊ธฐ๊ฐ ์๋ฃ๋๋ฉด FindSessionCompleteDelegate์ ๋ฑ๋ก๋ OnFindSessionComplete()ํจ์๊ฐ ํธ์ถ๋๋ค.
(2) OnFindSessionComplete()์์ session์ ์ฐธ์ฌํ๋ค.
(3) session ์ฐธ์ฌ๊ฐ ์๋ฃ๋๋ฉด JoinSessionCompleteDelegate์ ๋ฑ๋ก๋ OnJoinSessionComplate()ํจ์๊ฐ ํธ์ถ๋๋ค.
(4) OnJoinSessionComplate()์์ ์ฐธ์ฌํ session์ IP ์ฃผ์๋ฅผ ์ป์ด ClientTravel()ํจ์๋ฅผ ์ด์ฉํด ์๋ฒ์ ์ฐธ์ฌํ๋ค.
๊ตฌํ
1. ์ฐ์ ์ด์ ์ ์ฝ๋์ CreateGameSession()ํจ์์์ SessionSetting์ ์ต์ ์ ํ๋ ์ถ๊ฐํด์ค๋ค.
SessionSettings->Set(FName("MatchType"), FString("FreeForAll"), EOnlineDataAdvertisementType::ViaOnlineServiceAndPing); // ์ธ์
์ MatchType์ ๋ชจ๋์๊ฒ ์ด๋ฆผ, ์จ๋ผ์ธ์๋น์ค์ ํ์ ํตํด ์ธ์
ํ๋ณด ์ต์
์ผ๋ก ์ค์
FOnlineSessionSettings์ Setํจ์๋ SessionSettingํ ๋ Key์ Value ์ง์ผ๋ก ์ต์ ์ ์ธํ ํด์ฃผ๋ ํจ์๋ค.
์ ์ฝ๋๋ ์ธ์ ์ MatchType์ '๋ชจ๋์๊ฒ ์ด๋ฆผ(FreeForAll)'์ผ๋ก ์ค์ ํ๊ณ , ์จ๋ผ์ธ ์๋น์ค์ ํ์ ํตํด ์ธ์ ์ ํ๋ณดํ ์ ์๊ฒ ์ค์ ํ๋ ์ฝ๋์ด๋ค.
2. JoinGameSession()์ ๊ตฌํํ๋ค.
์ด ํจ์์์๋ ์ธ์ ๊ฒ์ ์ต์ ์ ์ค์ ํ๊ณ , ์ธ์ ์ ๊ฒ์ํ๋ค.
void AMenuSystemCharacter::JoinGameSession()
{
// ์ธ์
์ธํฐํ์ด์ค ์ ํจ์ฑ ๊ฒ์ฌ
if (!OnlineSessionInterface.IsValid())
{
// log
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Red, FString(TEXT("Game Session Interface is invailed")));
}
return;
}
// Find Session Complete Delegate ๋ฑ๋ก
OnlineSessionInterface->AddOnFindSessionsCompleteDelegate_Handle(FindSessionCompleteDelegate);
// Find Game Session
SessionSearch = MakeShareable(new FOnlineSessionSearch());
SessionSearch->MaxSearchResults = 10000; // ๊ฒ์ ๊ฒฐ๊ณผ๋ก ๋์ค๋ ์ธ์
์ ์ต๋๊ฐ
SessionSearch->bIsLanQuery = false; // LAN ์ฌ์ฉ ์ฌ๋ถ
SessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals); // ์ฐพ์ ์ธ์
์ฟผ๋ฆฌ๋ฅผ ํ์ฌ๋ก ์ค์ ํ๋ค
const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
OnlineSessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), SessionSearch.ToSharedRef());
}
3. Session์ ์ฐพ์ผ๋ฉด ํธ์ถ๋ Delegate์ Callback ํจ์๋ก OnFindSessionComplete()๋ฅผ ๋ฐ์ธ๋ฉํด์ค๋ค.
Session์ ์์ฑํ ๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฉค๋ฒ ๋ณ์๋ก FOnFindSessionsCompleteDelegateํ์ ์ FindSessionCompleteDelegate๋ฅผ ์ ์ธํด์ฃผ๊ณ , ์์ฑ์์์ ์ด Delegate์ Callback ํจ์๋ก OnFindSessionComplete()ํจ์๋ฅผ ๋ฐ์ธ๋ฉํด์ค๋ค.
AMenuSystemCharacter::AMenuSystemCharacter()
: CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCreateSessionComplete))
, FindSessionCompleteDelegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnFindSessionComplete))
{
...
}
4. OnFindSessionComplete() ํจ์๋ฅผ ๊ตฌํํ๋ค.
์ด ํจ์์์๋ ์ธ์ ๋ค์ ์ฐพ๊ณ ์ธ์ ์ ๋งค์น ํ์ ์ด 'FreeForAll'์ผ ๊ฒฝ์ฐ, ์ธ์ ์ ์ฐธ๊ฐํ๋ค.
void AMenuSystemCharacter::OnFindSessionComplete(bool bWasSuccessful)
{
if(!OnlineSessionInterface.IsValid()
|| !bWasSuccessful)
return;
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Cyan, FString(TEXT("======== Search Result ========")));
}
for (auto Result : SessionSearch->SearchResults)
{
FString Id = Result.GetSessionIdStr();
FString User = Result.Session.OwningUserName;
// ๋งค์น ํ์
ํ์ธํ๊ธฐ
FString MatchType;
Result.Session.SessionSettings.Get(FName("MatchType"), MatchType);
// ์ฐพ์ ์ธ์
์ ์ ๋ณด ์ถ๋ ฅํ๊ธฐ
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Cyan, FString::Printf(TEXT("Session ID : %s / Owner : %s"), *Id, *User));
}
// ์ธ์
์ ๋งค์น ํ์
์ด "FreeForAll"์ผ ๊ฒฝ์ฐ ์ธ์
์ฐธ๊ฐ
if (MatchType == FString("FreeForAll"))
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Cyan, FString::Printf(TEXT("Joining Match Type : %s"), *MatchType));
}
// Join Session Complete Delegate ๋ฑ๋ก
OnlineSessionInterface->AddOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegate);
const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
OnlineSessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, Result);
}
}
}
5. Session์ ์ฐธ์ฌํ๋ฉด ํธ์ถ๋ Delegate์ Callback ํจ์๋ก OnJoinSessionComplete()๋ฅผ ๋ฐ์ธ๋ฉํด์ค๋ค.
Session์ ์์ฑํ ๋, ์ฐพ์ ๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฉค๋ฒ ๋ณ์๋ก FOnJoinSessionsCompleteDelegateํ์ ์ JoinSessionCompleteDelegate๋ฅผ ์ ์ธํด์ฃผ๊ณ , ์์ฑ์์์ ์ด Delegate์ Callback ํจ์๋ก OnJoinSessionComplete()ํจ์๋ฅผ ๋ฐ์ธ๋ฉํด์ค๋ค.
AMenuSystemCharacter::AMenuSystemCharacter()
: CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCreateSessionComplete))
, FindSessionCompleteDelegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnFindSessionComplete))
, JoinSessionCompleteDelegate(FOnJoinSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnJoinSessionComplate))
{
...
}
6. OnJoinSessionComplete()๋ฅผ ๊ตฌํํ๋ค.
์ด ํจ์์์๋ ์ธ์ ์ ์ฐธ์ฌํ๋ค๋ฉด ์ฐธ์ฌํ ์ธ์ ์ IP ์ฃผ์๋ก ์ ์ํ๋ค.
void AMenuSystemCharacter::OnJoinSessionComplate(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
if (!OnlineSessionInterface.IsValid())
return;
// ์ธ์
์ ์กฐ์ธํ๋ค๋ฉด IP Address์ป์ด์์ ํด๋น ์๋ฒ์ ์ ์
FString Address;
if (OnlineSessionInterface->GetResolvedConnectString(NAME_GameSession, Address))
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Yellow, FString::Printf(TEXT("Connect String : %s"), *Address));
}
APlayerController* PlayerController = GetGameInstance()->GetFirstLocalPlayerController();
if (PlayerController)
{
PlayerController->ClientTravel(Address, ETravelType::TRAVEL_Absolute);
}
}
}
๊ฒฐ๊ณผ