목차

     

     


     

     

     

     


     

    MultiplayerSessionsSubsystem

     

     

    MultiplayerSessionsSubsystem.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Subsystems/GameInstanceSubsystem.h"
    #include "Interfaces/OnlineSessionInterface.h"
    #include "MultiplayerSessionsSubsystem.generated.h"
    //
    // Delcaring our own custom delegates for the Menu class to bind callbacks to
    //
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMultiplayerOnCreateSessionComplete, bool, bWasSuccessful);
    DECLARE_MULTICAST_DELEGATE_TwoParams(FMultiplayerOnFindSessionsComplete, const TArray<FOnlineSessionSearchResult>& SessionResults, bool bWasSuccessful);
    DECLARE_MULTICAST_DELEGATE_OneParam(FMultiplayerOnJoinSessionComplete, EOnJoinSessionCompleteResult::Type Result);
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMultiplayerOnDestroySessionComplete, bool, bWasSuccessful);
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMultiplayerOnStartSessionComplete, bool, bWasSuccessful);
    UCLASS()
    class MULTIPLAYERSESSIONS_API UMultiplayerSessionsSubsystem : public UGameInstanceSubsystem
    {
    GENERATED_BODY()
    public:
    UMultiplayerSessionsSubsystem();
    //
    // To handle session functionality. The Menu class will call these
    //
    void CreateSession(int32 NumPublicConnections, FString MatchType);
    void FindSessions(int32 MaxSearchResults);
    void JoinSession(const FOnlineSessionSearchResult& SessionResult);
    void DestroySession();
    void StartSession();
    //
    // Our own custom delegates for the Menu class to bind callbacks to
    //
    FMultiplayerOnCreateSessionComplete MultiplayerOnCreateSessionComplete;
    FMultiplayerOnFindSessionsComplete MultiplayerOnFindSessionsComplete;
    FMultiplayerOnJoinSessionComplete MultiplayerOnJoinSessionComplete;
    FMultiplayerOnDestroySessionComplete MultiplayerOnDestroySessionComplete;
    FMultiplayerOnStartSessionComplete MultiplayerOnStartSessionComplete;
    protected:
    // Internal callbacks for the delegates we'll add to the Online Session Interface delegate list.
    // 아래의 함수들은 이 클래스 밖에서 콜하지 않는다.
    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);
    private:
    IOnlineSessionPtr SessionInterface;
    TSharedPtr<FOnlineSessionSettings> LastSessionSettings;
    TSharedPtr<FOnlineSessionSearch> LastSessionSearch;
    //
    // To add to the Online Session Interface delegate list.
    // We'll bind our MultiplayerSessionsSubsystem internal callbacks to these.
    //
    FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate;
    FDelegateHandle CreateSessionCompleteDelegateHandle;
    FOnFindSessionsCompleteDelegate FindSessionsCompleteDelegate;
    FDelegateHandle FindSessionsCompleteDelegateHandle;
    FOnJoinSessionCompleteDelegate JoinSessionCompleteDelegate;
    FDelegateHandle JoinSessionCompleteDelegateHandle;
    FOnDestroySessionCompleteDelegate DestroySessionCompleteDelegate;
    FDelegateHandle DestroySessionCompleteDelegateHandle;
    FOnStartSessionCompleteDelegate StartSessionCompleteDelegate;
    FDelegateHandle StartSessionCompleteDelegateHandle;
    };

    변수 추가

    • TSharedPtr<FOnlineSessionSearch> LastSessionSearch;

     

     

     

     

    MultiplayerSessionsSubsystem.cpp

    더보기
    #include "MultiplayerSessionsSubsystem.h"
    #include "OnlineSubsystem.h"
    #include "OnlineSessionSettings.h"
    UMultiplayerSessionsSubsystem::UMultiplayerSessionsSubsystem(): //Delegate을 만들어 On~함수에 연결한다.
    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();//SessionInterface 변수에 IOnlineSubsystem의 SessionInterface 정보를 담는다.
    }
    }
    void UMultiplayerSessionsSubsystem::CreateSession(int32 NumPublicConnections, FString MatchType)
    {
    if (!SessionInterface.IsValid())
    {
    return;
    }
    //이미 존재하는 Session이 있다면 제거해준다.
    auto ExistingSession = SessionInterface->GetNamedSession(NAME_GameSession);
    if (ExistingSession != nullptr)
    {
    SessionInterface->DestroySession(NAME_GameSession);
    }
    // 새로 만드는 Session을 세팅해준다.
    // FDelegateHandle 내에 delegate을 저장한다. 그리고 추후에 Delegate List에서 제거한다.
    // Store the delegate in a FDelegateHandle so we can later remove it from the delegate list
    CreateSessionCompleteDelegateHandle = SessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate);
    LastSessionSettings = MakeShareable(new FOnlineSessionSettings());
    LastSessionSettings->bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true : false;//Steam Subsystem에 연결하는 경우는 LAN Match가 아니다. NULL Subsystem을 사용하는 경우 LAN Match다.
    LastSessionSettings->NumPublicConnections = NumPublicConnections;//함수 Input값을 적용. 접속 가능한 Players 수 제한
    LastSessionSettings->bAllowJoinInProgress = true;//Session이 on going일 때 참가할 수 있게 설정. Session이 실행중일 때 Player들이 원할 때 들어올 수 있음
    LastSessionSettings->bAllowJoinViaPresence = true;//Steam 기준에서 같은 region에 있는 Player들만 들어올 수 있게 설정.
    LastSessionSettings->bShouldAdvertise = true;//Steam에서 Advertise가 가능하여 사람들이 찾아 들어올 수 있게 한다.
    LastSessionSettings->bUsesPresence = true;//같은 region에서 session을 찾을 수 있게 해준다.
    LastSessionSettings->Set(FName("MatchType"), MatchType, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
    const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
    if (false == SessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, *LastSessionSettings))//CreateSession 리턴값이 false라면(=Session 만들기에 실패한다면)
    {
    //Delegate Handle를 사용하여 Delegate List에서 제거한다.
    SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegateHandle);
    // 헤더에서 만든 MultiplayerOnCreateSessionComplete delegate을 Broadcast 해준다.
    // Broadcast our own custom delegate
    MultiplayerOnCreateSessionComplete.Broadcast(false);//위의 if조건에서는 false
    }
    }
    void UMultiplayerSessionsSubsystem::FindSessions(int32 MaxSearchResults)
    {
    if (false == SessionInterface.IsValid())
    {
    return;
    }
    //MultiplayerSessionsSubsystem.h 내의 FindSessionsCompleteDelegate을 연결시킨다.
    FindSessionsCompleteDelegateHandle = SessionInterface->AddOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegate);
    LastSessionSearch = MakeShareable(new FOnlineSessionSearch());//생성
    LastSessionSearch->MaxSearchResults = MaxSearchResults;//DevID 찾기 최대 개수.
    LastSessionSearch->bIsLanQuery = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true : false;//Steam Subsystem에 연결하는 경우는 LAN Match가 아니다. NULL Subsystem을 사용하는 경우 LAN Match다.
    LastSessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);
    const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
    if (false == SessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), LastSessionSearch.ToSharedRef()))//FindSession 리턴값이 false라면(=Session 찾기에 실패했다면)
    {
    //Delegate Handle를 사용하여 FindSessionsCompleteDelegateHandle을 Delegate List에서 제거한다.
    SessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegateHandle);
    //헤더에서 만든 MultiplayerOnFindSessionComplete delegate을 Broadcast 해준다.
    MultiplayerOnFindSessionsComplete.Broadcast(TArray<FOnlineSessionSearchResult>(), false);//menu가 이 Broadcast를 받을 때 false로 받으면 FOnlineSessionSearchResult 배열이 비어있다는 것을 알 수 있다.
    }
    }
    void UMultiplayerSessionsSubsystem::JoinSession(const FOnlineSessionSearchResult& SessionResult)
    {
    if (false == SessionInterface.IsValid())//SessionInterface가 없다면
    {
    //Menu에 UnknownError라고(=JoinSession 할 수 없다고) 알려준다.
    MultiplayerOnJoinSessionComplete.Broadcast(EOnJoinSessionCompleteResult::UnknownError);
    return;
    }
    JoinSessionCompleteDelegateHandle = SessionInterface->AddOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegate);
    const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
    if (false == SessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, SessionResult))//JoinSession 리턴값이 false라면(=Session Join에 실패했다면)
    {
    SessionInterface->ClearOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegateHandle);
    MultiplayerOnJoinSessionComplete.Broadcast(EOnJoinSessionCompleteResult::UnknownError);
    }
    }
    void UMultiplayerSessionsSubsystem::DestroySession()
    {
    }
    void UMultiplayerSessionsSubsystem::StartSession()
    {
    }
    void UMultiplayerSessionsSubsystem::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
    {
    //SessionInterfaces의 Delegate을 지워준다.
    if (SessionInterface)
    {
    SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegateHandle);
    }
    //MultiplayerOnCreateSessionComplete delegate를 Broadcast 해준다. 이렇게하면 Menu 클래스는 callback function 가지게 된다.
    MultiplayerOnCreateSessionComplete.Broadcast(bWasSuccessful);
    }
    //Session을 성공적으로 찾은 경우 콜 되는 함수
    void UMultiplayerSessionsSubsystem::OnFindSessionsComplete(bool bWasSuccessful)
    {
    if (SessionInterface)
    {
    SessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegateHandle);
    }
    if (LastSessionSearch->SearchResults.Num() <= 0)//SearchResults 배열 결과값을 순회에서 찾았을 때, 찾은것이 0이하라면(=아무것도 찾지 못했다면)
    {
    MultiplayerOnFindSessionsComplete.Broadcast(TArray<FOnlineSessionSearchResult>(), false);//menu가 이 Broadcast를 받을 때 false로 받으면 FOnlineSessionSearchResult 배열이 비어있다는 것을 알 수 있다.
    return;//밑의 코드가 진행되지 않도록 여기서 리턴 시켜준다.
    }
    MultiplayerOnFindSessionsComplete.Broadcast(LastSessionSearch->SearchResults, bWasSuccessful);
    }
    void UMultiplayerSessionsSubsystem::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
    {
    if (SessionInterface)
    {
    SessionInterface->ClearOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegateHandle);
    }
    //EOnJoinSessionCompleteResult를 Broadcast 해준다.
    MultiplayerOnJoinSessionComplete.Broadcast(Result);
    }
    void UMultiplayerSessionsSubsystem::OnDestroySessionComplete(FName SessionName, bool bWasSuccessful)
    {
    }
    void UMultiplayerSessionsSubsystem::OnStartSessionComplete(FName SessionName, bool bWasSuccessful)
    {
    }

    void UMultiplayerSessionsSubsystem::FindSessions(int32 MaxSearchResults)

    • if (false == SessionInterface.IsValid())
              return;
    •  FindSessionsCompleteDelegateHandle = SessionInterface->AddOnFindSessionsCompleteDelegate_Handle (FindSessionsCompleteDelegate);
    • LastSessionSearch = MakeShareable(new FOnlineSessionSearch());
    • LastSessionSearch->MaxSearchResults = MaxSearchResults;
    • LastSessionSearch->bIsLanQuery = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true : false;
    • LastSessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);
    • const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
          if (false == SessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), LastSessionSearch.ToSharedRef()))
          {
              SessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegateHandle);

              MultiplayerOnFindSessionsComplete.Broadcast(TArray<FOnlineSessionSearchResult>(), false); 
          }

     

    void UMultiplayerSessionsSubsystem::JoinSession(const FOnlineSessionSearchResult& SessionResult)

    • if (false == SessionInterface.IsValid())
          {
              MultiplayerOnJoinSessionComplete.Broadcast(EOnJoinSessionCompleteResult::UnknownError);
              return;
          }
    • JoinSessionCompleteDelegateHandle = SessionInterface->AddOnJoinSessionCompleteDelegate_Handle (JoinSessionCompleteDelegate);
    • const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
    • if (false == SessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, SessionResult))
          {
              SessionInterface->ClearOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegateHandle);

              MultiplayerOnJoinSessionComplete.Broadcast(EOnJoinSessionCompleteResult::UnknownError);
          }

     

    void UMultiplayerSessionsSubsystem::OnFindSessionsComplete(bool bWasSuccessful)

    • if (SessionInterface)
          {
              SessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegateHandle);
          }

          if (LastSessionSearch->SearchResults.Num() <= 0)
          {
              MultiplayerOnFindSessionsComplete.Broadcast(TArray<FOnlineSessionSearchResult>(), false);
              return;
          }

          MultiplayerOnFindSessionsComplete.Broadcast(LastSessionSearch->SearchResults, bWasSuccessful);

     

    void UMultiplayerSessionsSubsystem::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)

    •     if (SessionInterface)
          {
              SessionInterface->ClearOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegateHandle);
          }
          MultiplayerOnJoinSessionComplete.Broadcast(Result);

     

     


     

     

     

     

    Menu.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Blueprint/UserWidget.h"
    #include "Interfaces/OnlineSessionInterface.h"//EOnJoinSessionCompleteResult 사용을 위한 헤더
    #include "Menu.generated.h"
    UCLASS()
    class MULTIPLAYERSESSIONS_API UMenu : public UUserWidget
    {
    GENERATED_BODY()
    public:
    UFUNCTION(BlueprintCallable)
    void MenuSetup(int32 NumberOfPublicConnections = 4, FString TypeOfMatch = FString(TEXT("FreeForAll")));//접속할 수 있는 Player 숫자를 input으로 만들고 4를 기본값으로 설정한다.
    protected:
    virtual bool Initialize() override;
    virtual void OnLevelRemovedFromWorld(ULevel* InLevel, UWorld* InWorld) override;//다른 Level로 이동하면 기존의 Level을 지우는 함수.
    //
    // Callbacks for the custom delegates on the MultiplayerSessionsSubsystem
    // MultiplayerSessionsSubsystem.h의 Dynamic Delegate과 연결된다. Dynamic과 연결되는 경우 UFUNCTION()을 꼭 붙여야 한다. 붙이지 않으면 dynamic delegate과 연결되지 않는다.
    UFUNCTION()
    void OnCreateSession(bool bWasSuccessful);
    void OnFindSessions(const TArray<FOnlineSessionSearchResult>& SessionResults, bool bWasSuccessful);
    void OnJoinSession(EOnJoinSessionCompleteResult::Type Result);
    UFUNCTION()
    void OnDestroySession(bool bWasSuccessful);
    UFUNCTION()
    void OnStartSession(bool bWasSuccessful);
    private:
    //meta = (BindWidget)을 사용하면 BP의 Button Widget이 아래의 변수와 연결된다. 이 때 BP와 C++변수 이름은 일치하여야 한다.
    UPROPERTY(meta = (BindWidget))
    class UButton* HostButton;
    UPROPERTY(meta = (BindWidget))
    UButton* JoinButton;
    UFUNCTION()
    void HostButtonClicked();
    UFUNCTION()
    void JoinButtonClicked();
    void MenuTearDown();
    // The subsystem designed to handle all online session functionality
    class UMultiplayerSessionsSubsystem* MultiplayerSessionsSubsystem;
    int32 NumPublicConnections{ 4 };
    FString MatchType{ TEXT("FreeForAll") };
    };

    변경사항 없음.

     

     

     

     

    Menu.cpp

    더보기
    #include "Menu.h"
    #include "Components/Button.h"
    #include "MultiplayerSessionsSubsystem.h"
    #include "OnlineSessionSettings.h"
    #include "OnlineSubsystem.h"
    void UMenu::MenuSetup(int32 NumberOfPublicConnections, FString TypeOfMatch)
    {
    NumPublicConnections = NumberOfPublicConnections;
    MatchType = TypeOfMatch;
    AddToViewport();
    SetVisibility(ESlateVisibility::Visible);
    bIsFocusable = true;
    UWorld* World = GetWorld();
    if (World)
    {
    APlayerController* PlayerController = World->GetFirstPlayerController();
    if (PlayerController)
    {
    FInputModeUIOnly InputModeData;
    InputModeData.SetWidgetToFocus(TakeWidget());
    InputModeData.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
    PlayerController->SetInputMode(InputModeData);
    PlayerController->SetShowMouseCursor(true);
    }
    }
    UGameInstance* GameInstance = GetGameInstance();
    if (GameInstance)
    {
    //헤더에서 만든 MultiplayerSessionsSubsystem 변수에 Subsystem을 리턴 값을 넣어준다.
    MultiplayerSessionsSubsystem = GameInstance->GetSubsystem<UMultiplayerSessionsSubsystem>();
    }
    if (MultiplayerSessionsSubsystem)
    {
    //callback을 Bind해준다.
    MultiplayerSessionsSubsystem->MultiplayerOnCreateSessionComplete.AddDynamic(this, &ThisClass::OnCreateSession);//Dynamic을 Bind하는 경우는 AddDynamic 사용.
    MultiplayerSessionsSubsystem->MultiplayerOnFindSessionsComplete.AddUObject(this, &ThisClass::OnFindSessions);//Dynamic이 아닌 것을 Bind하는 경우는 AddUObject 사용.
    MultiplayerSessionsSubsystem->MultiplayerOnJoinSessionComplete.AddUObject(this, &ThisClass::OnJoinSession);
    MultiplayerSessionsSubsystem->MultiplayerOnDestroySessionComplete.AddDynamic(this, &ThisClass::OnDestroySession);
    MultiplayerSessionsSubsystem->MultiplayerOnStartSessionComplete.AddDynamic(this, &ThisClass::OnStartSession);
    }
    }
    bool UMenu::Initialize()
    {
    //Super버젼이 false면 false를 리턴한다.(=상위 클래스에서 Initialize 하는게 없으면 false를 리턴하여 Initialize()를 하지 않는다.)
    if (!Super::Initialize())
    {
    return false;
    }
    if (HostButton)
    {
    //HostButton 클릭할 때 발생하는 이벤트를 Delegate로 연결해준다.
    HostButton->OnClicked.AddDynamic(this, &ThisClass::HostButtonClicked);
    }
    if (JoinButton)
    {
    //JoinButton 클릭할 때 발생하는 이벤트를 Delegate로 연결해준다.
    JoinButton->OnClicked.AddDynamic(this, &ThisClass::JoinButtonClicked);
    }
    return true;
    }
    void UMenu::OnLevelRemovedFromWorld(ULevel* InLevel, UWorld* InWorld)
    {
    MenuTearDown();//Widget을 뷰포트에서 지우고 input mode가 리셋된다.
    Super::OnLevelRemovedFromWorld(InLevel, InWorld);
    }
    void UMenu::OnCreateSession(bool bWasSuccessful)
    {
    if (bWasSuccessful)
    {
    if (GEngine)
    {
    GEngine->AddOnScreenDebugMessage(
    -1,
    15.f,
    FColor::Yellow,
    FString(TEXT("Session created successfully!"))
    );
    }
    UWorld* World = GetWorld();
    if (World)
    {
    World->ServerTravel("/Game/ThirdPerson/Maps/Lobby?listen");
    }
    }
    else//실패한 경우
    {
    if (GEngine)
    {
    GEngine->AddOnScreenDebugMessage(
    -1,
    15.f,
    FColor::Red,
    FString(TEXT("Failed to create session!"))
    );
    }
    }
    }
    void UMenu::OnFindSessions(const TArray<FOnlineSessionSearchResult>& SessionResults, bool bWasSuccessful)
    {
    if (MultiplayerSessionsSubsystem == nullptr)
    {
    return;
    }
    for (auto Result : SessionResults)//변수로 받은 SessionResults배열을 순회하며 검색
    {
    FString SettingsValue;
    Result.Session.SessionSettings.Get(FName("MatchType"), SettingsValue);
    //SessionSettings의 결과값이 "MatchType"과 SetingsValue을 가지고 있는지 확인.
    if (SettingsValue == MatchType)
    {
    MultiplayerSessionsSubsystem->JoinSession(Result);
    return;
    }
    }
    }
    void UMenu::OnJoinSession(EOnJoinSessionCompleteResult::Type Result)
    {
    //IOnlineSubsystem 사용을 위해 위에 #include "OnlineSubsystem.h" 추가
    IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get();
    if (Subsystem)
    {
    IOnlineSessionPtr SessionInterface = Subsystem->GetSessionInterface();
    if (SessionInterface.IsValid())
    {
    FString Address;
    SessionInterface->GetResolvedConnectString(NAME_GameSession, Address);
    APlayerController* PlayerController = GetGameInstance()->GetFirstLocalPlayerController();
    if (PlayerController)
    {
    PlayerController->ClientTravel(Address, ETravelType::TRAVEL_Absolute);
    }
    }
    }
    }
    void UMenu::OnDestroySession(bool bWasSuccessful)
    {
    }
    void UMenu::OnStartSession(bool bWasSuccessful)
    {
    }
    void UMenu::HostButtonClicked()
    {
    //디버깅용
    if (GEngine)
    {
    GEngine->AddOnScreenDebugMessage(
    -1,
    15.f,
    FColor::Yellow,
    FString(TEXT("Host Button Clicked"))
    );
    }
    if (MultiplayerSessionsSubsystem)
    {
    MultiplayerSessionsSubsystem->CreateSession(NumPublicConnections, MatchType);//NumPublicConnections 숫자 크기까지 Players 접속 가능
    UWorld* World = GetWorld();
    }
    }
    void UMenu::JoinButtonClicked()
    {
    //디버깅 테스트
    if (GEngine)
    {
    GEngine->AddOnScreenDebugMessage(
    -1,
    15.f,
    FColor::Yellow,
    FString(TEXT("Join Button Clicked"))
    );
    }
    if (MultiplayerSessionsSubsystem)
    {
    //Steam DevID의 숫자가 클수도 있으니 MaxSearchResults값을 10000으로 넉넉히 잡는다.
    MultiplayerSessionsSubsystem->FindSessions(10000);
    }
    }
    void UMenu::MenuTearDown()
    {
    RemoveFromParent();
    UWorld* World = GetWorld();
    if (World)
    {
    APlayerController* PlayerController = World->GetFirstPlayerController();
    if (PlayerController)
    {
    FInputModeGameOnly InputModeData;
    PlayerController->SetInputMode(InputModeData);
    PlayerController->SetShowMouseCursor(false);
    }
    }
    }

    헤더 추가

    • #include "OnlineSubsystem.h"

     

    void UMenu::OnFindSessions(const TArray<FOnlineSessionSearchResult>& SessionResults, bool bWasSuccessful)

    • SessionResults 중 SettingsValue == MatchType이 있다면 
      • MultiplayerSessionsSubsystem->JoinSession(Result);

     

    void UMenu::OnJoinSession(EOnJoinSessionCompleteResult::Type Result)

    • IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get();
    • SessionInterface->GetResolvedConnectString(NAME_GameSession, Address);

     

    void UMenu::JoinButtonClicked()

    • if (MultiplayerSessionsSubsystem)
      • MultiplayerSessionsSubsystem->FindSessions(10000);