Join Session
대망의 JoinSession 어떻게 하는지 보자.
Create Sesssion때처럼 헤더파일에 JoinSession 함수 선언, 델리게이트와 콜백함수도 작성한다.
UFUNCTION(BlueprintCallable)
void JoinGameSession();
void OnFindSessionsComplete(bool bWasSuccessful);
private:
FOnFindSessionsCompleteDelegate FindSessionsCompleteDelegate;
생성자에 델리게이트를 바인딩 해주고, JoinGameSession 함수 구현
void AMenuCharacter::JoinGameSession()
{
// Find game sessions
if (!OnlineSessionInterface.IsValid()) {
return;
}
OnlineSessionInterface->AddOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegate);
TSharedPtr<FOnlineSessionSearch> SessionSearch = MakeShareable(new FOnlineSessionSearch());
SessionSearch->MaxSearchResults = 10000;
SessionSearch->bIsLanQuery = false;
const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
OnlineSessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), SessionSearch.ToSharedRef());
}
그리고 위에서 선언한 "TSharedPtr<FOnlineSessionSearch> SessionSearch" 변수에서 SearchResults를 가져와야하기 때문에 로컬 변수로 선언하지 말고 헤더로 빼준다.
그리고 SessionSearch 옵션 중 "SessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);"
설정을 통해 현재 존재하는 세션만 검색하도록 설정해준다.
이후 콜백함수에 SearchResult를 순회하며 결과를 보도록 작성
void AMenuCharacter::OnFindSessionsComplete(bool bWasSuccessful)
{
for (auto Result : SessionSearch->SearchResults) {
FString Id = Result.GetSessionIdStr();
FString User = Result.Session.OwningUserName;
if (GEngine) {
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Cyan,
FString::Printf(TEXT("Id: %s, User: %s"), *Id, *User)
);
}
}
}
그다음 다음과 같은 구문을 CreateSession에 추가
SessionSettings->Set(FName("MatchType"), FString("FreeForAll"), EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
MatchType이라는 Key의 Value값을 FreeForAll로 정하고, 세션 설정 데이터가 온라인 서비스와 핑 두가지 모두를 이용하여 전달될 수 있도록 설정 -> 플레이어가 세션을 검색할때 두가지 정보를 모두 이용 가능
OnFindSessionsComplete 콜백 함수에도 해당 타입을 구분하도록 추가
FString MatchType = "FreeForAll";
Result.Session.SessionSettings.Get(FName("MatchType"), MatchType);
if (MatchType == FString("FreeForAll")) {
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Cyan,
FString::Printf(TEXT("Joining Match Type: %s"), *MatchType)
);
}
그다음 JoinSessionCompleteDelegate 헤더파일에 추가 -> 실질적인 ClientTravel이 일어날 부분
void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result);
FOnJoinSessionCompleteDelegate JoinSessionCompleteDelegate;
EOnJoinSessionCompleteResult::Type Result -> 이 파라미터는 세션 참가 시도 후 결과값을 나타내는 Enum 변수.
AlreadyInSession, SessionDestroy같은 값들이 결과값으로 도출된다.
cpp 파일의 생성자에도 델리게이트 및 콜백함수 등록
AMenuCharacter::AMenuCharacter():
CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCreateSessionComplete)),
FindSessionsCompleteDelegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnFindSessionsComplete)),
JoinSessionCompleteDelegate(FOnJoinSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnJoinSessionComplete))
그리고 클래스 명을 ThisClass로 바꿔서 테스트 후 본 프로젝트에 이식하기 용이하도록 변경
그다음 OnJoinSessionComplete 함수 구현
void AMenuCharacter::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
if (!OnlineSessionInterface.IsValid()) {
return;
}
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);
}
}
}
여기서 ClientTravel의 파라미터는
- Address: 이동할 레벨. IP주소나 도메인, 로컬맵 등등이 들어갈 수 있다.
- ETravelType::Travel_Absolute: Address를 절대경로로 처리한다. 이전 레벨이나 세션 상태와 관계없이 지정된 맵이나 서버로 이동한다.
- Travel Type은 Relative와 Partial도 있다.
이후 테스트를 해보면 세션 생성 및 탐색은 잘 동작하며, 세션 참가 자체는 dev키가 테스트를 위한 공용키라 지금처럼 하드코딩 된 상태로는 작동하지 않는것을 확인할 수 있었다.
'개발 일지' 카테고리의 다른 글
플러그인 UI - 1 (0) | 2024.12.01 |
---|---|
플러그인 등록 (0) | 2024.11.30 |
OnlineSubsystem Steam 연결 및 Create Session (0) | 2024.11.27 |
Listen Server와 Dedicated Server (0) | 2024.11.26 |
계속되는 세션 오류 (0) | 2024.11.22 |