1.创建委托并绑定回调,实现解耦
/* 创建会话完成 */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMultiPlayerOnCreateSessionCompleted, bool, bWasSuccessful);
/* 开始会话完成 */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMultiPlayerOnStartSessionComplted, bool, bWasSuccessful);
/* 销毁会话完成 */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMultiPlayerOnDestorySessionCompleted, bool, bWasSuccessful);/* 发现会话完成 */
DECLARE_MULTICAST_DELEGATE_TwoParams(FMultiPlayerOnFindSessionCompleted,const TArray<FOnlineSessionSearchResult>& SessoinResults, bool bWasSuccessful);/* 加入会话完成 */
DECLARE_MULTICAST_DELEGATE_OneParam(FMultiPlayerOnJoinSessionCompleted, bool bWasSuccessful);FMultiPlayerOnCreateSessionCompleted MultiPlayerOnCreateSessionCompleted;FMultiPlayerOnStartSessionComplted MultiPlayerOnStartSessionComplted;FMultiPlayerOnDestorySessionCompleted MultiPlayerOnDestorySessionCompleted;FMultiPlayerOnFindSessionCompleted MultiPlayerOnFindSessionCompleted;FMultiPlayerOnJoinSessionCompleted MultiPlayerOnJoinSessionCompleted;
UFUNCTION()
void OnCreateSession(bool bWasSuccessful);UFUNCTION()
void OnStartSession(bool bWasSuccessful);UFUNCTION()
void OnDestorySession(bool bWasSuccessful);void OnFindSession(const TArray<FOnlineSessionSearchResult>& SessoinResults, bool bWasSuccessful);void OnJoinSession(bool bWasSuccessful);MultiplayerSessionsSubsystem->MultiPlayerOnCreateSessionCompleted.AddDynamic(this, &ThisClass::OnCreateSession);
MultiplayerSessionsSubsystem->MultiPlayerOnStartSessionComplted.AddDynamic(this, &ThisClass::OnStartSession);
MultiplayerSessionsSubsystem->MultiPlayerOnDestorySessionCompleted.AddDynamic(this, &ThisClass::OnDestorySession);MultiplayerSessionsSubsystem->MultiPlayerOnFindSessionCompleted.AddUObject(this, &ThisClass::OnFindSession);
MultiplayerSessionsSubsystem->MultiPlayerOnJoinSessionCompleted.AddUObject(this, &ThisClass::OnJoinSession);
2.发现会话
当加入会话按钮点击时
void UMenu::OnJoinButtonClicked()
{Print(TEXT("JoinButton is Clicked!!!"));if (MultiplayerSessionsSubsystem){MultiplayerSessionsSubsystem->FindSessions(10000);}
}
设置会话搜索条件,并存储会话的搜索结果
/* 会话搜索条件 */
TSharedPtr<FOnlineSessionSearch> SessionSearch;
/* 查找会话 */
void UMultiplayerSessionsSubsystem::FindSessions(int32 MaxSearchResults)
{// 1.检查管理会话的接口if (!OnlineSessionInterface)return;// 2.获取当查找到会话时的句柄OnFindSessionsCompleteDelegateHandle = OnlineSessionInterface->AddOnFindSessionsCompleteDelegate_Handle(OnFindSessionsCompleteDelegate);// 3.设置会话搜索的条件SessionSearch = MakeShareable(new FOnlineSessionSearch);SessionSearch->bIsLanQuery = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true : false;SessionSearch->MaxSearchResults = MaxSearchResults;SessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);// 4.查找会话ULocalPlayer* LocalPC = GetWorld()->GetFirstLocalPlayerFromController();if (!OnlineSessionInterface->FindSessions(*LocalPC->GetPreferredUniqueNetId(), SessionSearch.ToSharedRef())){// 查找会话失败OnlineSessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(OnFindSessionsCompleteDelegateHandle);// 广播会话失败MultiPlayerOnFindSessionCompleted.Broadcast(TArray<FOnlineSessionSearchResult>(),false);}
}
执行查找会话指令成功
/* 查找会话完成对应的回调 */
void UMultiplayerSessionsSubsystem::OnFindSessionsComplete(bool bWasSuccessful)
{if (OnlineSessionInterface){OnlineSessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(OnFindSessionsCompleteDelegateHandle);}if (SessionSearch->SearchResults.Num() <= 0){MultiPlayerOnFindSessionCompleted.Broadcast(TArray<FOnlineSessionSearchResult>(), false);return;}MultiPlayerOnFindSessionCompleted.Broadcast(SessionSearch->SearchResults, bWasSuccessful);
}
当查找到会话时,遍历查找到的会话结果找到匹配的会话,加入该会话
// 当查找会话指令执行时
void UMenu::OnFindSession(const TArray<FOnlineSessionSearchResult>& SessoinResults, bool bWasSuccessful)
{// 查找到会话if (bWasSuccessful){for (auto& SessionResult : SessoinResults){// 1.获取会话的键所对应的ValueFString MatchSessionValue;SessionResult.Session.SessionSettings.Get("MatchType", MatchSessionValue);// 2.判断是不是要加入的会话if (MatchSessionValue == MatchType){MultiplayerSessionsSubsystem->JoinSession(SessionResult);return;}}}
}
3.加入会话
/* 加入会话 */
void UMultiplayerSessionsSubsystem::JoinSession(const FOnlineSessionSearchResult& SearchResult)
{// 1.检查管理会话的接口if (!OnlineSessionInterface.IsValid()){MultiPlayerOnJoinSessionCompleted.Broadcast(EOnJoinSessionCompleteResult::UnknownError);return;}// 2.管理加入会话的委托的生命周期OnJoinSessionCompleteDelegateHandle = OnlineSessionInterface->AddOnJoinSessionCompleteDelegate_Handle(OnJoinSessionCompleteDelegate);// 3.加入会话ULocalPlayer* LocalPC = GetWorld()->GetFirstLocalPlayerFromController();if (!OnlineSessionInterface->JoinSession(*LocalPC->GetPreferredUniqueNetId(), NAME_GameSession, SearchResult)){OnlineSessionInterface->ClearOnJoinSessionCompleteDelegate_Handle(OnJoinSessionCompleteDelegateHandle);MultiPlayerOnJoinSessionCompleted.Broadcast(EOnJoinSessionCompleteResult::UnknownError);}
}/* 加入会话完成对应的回调 */
void UMultiplayerSessionsSubsystem::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{if (OnlineSessionInterface){OnlineSessionInterface->ClearOnJoinSessionCompleteDelegate_Handle(OnJoinSessionCompleteDelegateHandle);}MultiPlayerOnJoinSessionCompleted.Broadcast(EOnJoinSessionCompleteResult::Success);
}
当加入会话指令执行成功时,跳转到会话的场景
/* 当加入会话指令执行完成时 */
void UMenu::OnJoinSession(EOnJoinSessionCompleteResult::Type Result)
{if (Result == EOnJoinSessionCompleteResult::Success){// 1.检查管理会话的接口if (MultiplayerSessionsSubsystem && MultiplayerSessionsSubsystem->OnlineSessionInterface){// 2.通过会话的名称来获取会话的地址并跳转到会话FString SessionAddress;MultiplayerSessionsSubsystem->OnlineSessionInterface->GetResolvedConnectString(NAME_GameSession, SessionAddress);APlayerController* PlayerController = GetGameInstance()->GetFirstLocalPlayerController();if (PlayerController){PlayerController->ClientTravel(SessionAddress, ETravelType::TRAVEL_Absolute);}}}
}
4.创建游戏模式
重载当客户端加进来时和退出时的函数
UCLASS()
class MULTIPLAYERSESSIONS_API ALobbyGameModeBase : public AGameModeBase
{GENERATED_BODY()public:/* 当玩家成功连接进入服务器时 */virtual void PostLogin(APlayerController* NewPlayer) override;/* 当玩家退出时 */virtual void Logout(AController* Exiting) override;
};
#include "LobbyGameModeBase.h"#include "GameFramework/GameStateBase.h"
#include "GameFramework/PlayerState.h"#include "PluginsDebugHelper.h"
using namespace Debug;void ALobbyGameModeBase::PostLogin(APlayerController* NewPlayer)
{Super::PostLogin(NewPlayer);if (GameState){int NumberOfPlayers = GameState.Get()->PlayerArray.Num();Print("Players in game: " + FString::FromInt(NumberOfPlayers));APlayerState* PlayerState = NewPlayer->GetPlayerState<APlayerState>();if (PlayerState){Print("Player " + PlayerState->GetName() + " has joined the game");}}
}void ALobbyGameModeBase::Logout(AController* Exiting)
{Super::Logout(Exiting);APlayerState* PlayerState = Exiting->GetPlayerState<APlayerState>();if (PlayerState){Print("Player " + PlayerState->GetName() + " has Exited the game");}
}
修改创建会话
// 在创建会话的函数里加上这一句
SessionSettings->BuildUniqueId = 1;
修改DefaultGame.ini
[/Script/EngineSettings.GeneralProjectSettings]
ProjectID=CA381F6F4A941684425AAFA0E51AE3FC
ProjectName=Third Person Game Template[StartupActions]
bAddPacks=True
InsertPack=(PackSource="StarterContent.upack",PackName="StarterContent")[/Script/Enginne.GameSession]
MaxPlayers=100
创建游戏模式蓝图