当前位置: 首页 > news >正文

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

创建游戏模式蓝图

由于测试时间比较繁琐,目前还在Debug,等后面慢慢找

相关文章:

  • 文件内容课堂总结
  • 14 nginx 的 dns 缓存的流程
  • 为了避免unboundLocalError和为什么X的值一直不变呢?
  • Gartner发布软件供应链安全市场指南:软件供应链安全工具的8个强制功能、9个通用功能及全球29家供应商
  • 如何查看linux history命令文件
  • 【pm2】pm2启动无法访问接口 ,node命令启动却可以
  • 使用nhdeep档案目录打印工具生成干部人事档案目录打印文件
  • 0501路由-react-仿低代码平台项目
  • [问题帖] vscode 重启远程终端
  • jsoup解析页面保留换行符
  • 计算机视觉色彩空间全解析:RGB、HSV与Lab的实战对比
  • 蓝桥杯C/C++省赛/国赛注意事项及运行环境配置
  • 淘宝商品数据实时抓取 API 开发指南:从接口申请到数据解析实战
  • [原创](现代Delphi 12指南): 设置、运行和调试你的第一个macOS应用程序.
  • JZ31 栈的压入、弹出序列
  • 穿透三层内网VPC1
  • 反转链表系列
  • UVa1367/LA3532 Nuclear Plants
  • 第十五届蓝桥杯大赛软件赛省赛Python 大学 B 组试做(下)【本期题单: 缴纳过路费, 纯职业小组】
  • Asp.NET Core WebApi 配置文件