TPS入门DAY04 服务器篇
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.获取会话的键所对应的Value
FString 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
创建游戏模式蓝图