《UE5_C++多人TPS完整教程》学习笔记12 ——《P13 加入游戏会话(Joining The Sessions)》


本文为B站系列教学视频 《UE5_C++多人TPS完整教程》 —— 《P13 加入游戏会话(Joining The Session)》 的学习笔记,该系列教学视频为 Udemy 课程 《Unreal Engine 5 C++ Multiplayer Shooter》 的中文字幕翻译版,UP主(也是译者)为 游戏引擎能吃么。


文章目录

  • P13 加入游戏会话
  • 13.1 创建关卡
  • 13.2 设置及检查匹配类型
  • 13.3 获取游戏会话创建源地址
  • 13.4 进行测试
  • 13.5 Summary


P13 加入游戏会话

本节课将在《P11 设置加入游戏会话(Setup for Joining Sessions)》 代码的基础上,创建一个新关卡 “Lobby”,以便玩家在加入已创建的会话后可以前往该关卡等待其他玩家加入;我们还将在会话设置中指定匹配类型(Match type),确保为游戏会话设置正确的匹配类型;当游戏会话被查找到时,首先检查匹配类型,然后自动获取游戏会话创建源 IP 地址,以便我们加入游戏会话后可以前往关卡 “Lobby”。
在这里插入图片描述


13.1 创建关卡

  1. 新建 Basic 类型关卡,命名为 “Lobby”,保存到 “Content\ThirdPerson\Maps” 目录下。
    在这里插入图片描述
  2. 修改 “MenuSystemcharacter.cpp” 中回调函数 “OnCreateSessionComplete()”:如果游戏会话创建成功,进入关卡 “Lobby”。
    void AMenuSystemCharacter::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
    {if (bWasSuccessful) {	// 如果游戏会话创建成功if (GEngine) {GEngine->AddOnScreenDebugMessage(	// 添加调试信息到屏幕上-1,								// 使用 -1 不会覆盖前面的调试信息15.f,							// 调试信息的显示时间FColor::Red,					// 字体颜色FString::Printf(TEXT("Create session: %s!"), *SessionName.ToString())	// 打印游戏会话的名称);}/* P13 加入游戏会话(Joining The Sessions)*/UWorld* World = GetWorld();if (World) {// Uworld->ServerTravel:https://docs.unrealengine.com/5.0/en-US/API/Runtime/Engine/Engine/UWorld/ServerTravel/World->ServerTravel(FString("/Game/ThirdPerson/Maps/Lobby?listen"));	// 作为监听服务器打开 Lobby 关卡}/* P13 加入游戏会话(Joining The Sessions)*/}else {	// 如果游戏会话创建失败...}
    }
    

13.2 设置及检查匹配类型

  1. 在函数 CreateGameSession() 的会话设置部分添加类型匹配设置。

    void AMenuSystemCharacter::CreateGameSession()	// 当按下数字键 1 时调用
    {...// 会话设置成员变量参阅及含义:https://docs.unrealengine.com/5.3/en-US/API/Plugins/OnlineSubsystem/FOnlineSessionSettings/SessionSettings->bIsLANMatch = false;			// 会话设置:不创建 LAN 连接SessionSettings->NumPublicConnections = 4;		// 会话设置:设置最大公共连接数为 4SessionSettings->bAllowJoinInProgress = true;	// 会话设置:在会话运行时允许其他玩家加入SessionSettings->bAllowJoinViaPresence = true;	// 会话设置:Steam 使用 Presence 搜索会话所在地区,确保连接正常工作SessionSettings->bShouldAdvertise = true;		// 会话设置:允许 Steam 发布会话SessionSettings->bUsesPresence = true;			// 会话设置:允许显示用户 Presence 信息SessionSettings->bUseLobbiesIfAvailable = true;	// (视频中未提及)会话设置:优先选择 Lobby API(Steam 支持 Lobby API)/* P13 加入游戏会话(Joining The Sessions)*/// void FOnlineSessionSettings::Set(FName Key, const FString& Value, EOnlineDataAdvertisementType::Type InType);SessionSettings->Set(FName("MatchType"), FString("FreeForAll"), EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);/* P13 加入游戏会话(Joining The Sessions)*/...
    }
    
  2. 在回调函数 “OnFindSessionsComplete()” 中加入对游戏会话搜索结果进行匹配类型检查的代码。

    void AMenuSystemCharacter::OnFindSessionsComplete(bool bWasSuccessful)
    {for (auto Result : SessionSearch->SearchResults) {	// 遍历游戏会话搜索结果FString Id = Result.GetSessionIdStr();FString User = Result.Session.OwningUserName;/* P13 加入游戏会话(Joining The Sessions)*/FString MatchType;	// 保存游戏会话匹配类型Result.Session.SessionSettings.Get(FName("MatchType"), MatchType);	// 获取游戏会话匹配类型保存在 MatchType 中/* P13 加入游戏会话(Joining The Sessions)*/if (GEngine) {GEngine->AddOnScreenDebugMessage(	// 添加调试信息到屏幕上-1,								// 使用 -1 不会覆盖前面的调试信息15.f,							// 调试信息的显示时间FColor::Cyan,					// 字体颜色:蓝绿色FString::Printf(TEXT("Id: %s, User: %s!"), *Id, *User)	// 打印消息);}/* P13 加入游戏会话(Joining The Sessions)*/if (MatchType == FString("FreeForAll")) {if (GEngine) {GEngine->AddOnScreenDebugMessage(	// 添加调试信息到屏幕上-1,								// 使用 -1 不会覆盖前面的调试信息15.f,							// 调试信息的显示时间FColor::Cyan,					// 字体颜色:蓝绿色FString::Printf(TEXT("Joining Match Type: %s!"), *MatchType)	// 打印游戏会话匹配类型);}}/* P13 加入游戏会话(Joining The Sessions)*/}
    }
    

13.3 获取游戏会话创建源地址

  1. 添加代码到 “MenuSystemcharacter.h” 的类 “AMenuSystemCharacter” 中,定义委托 JoinSessionsCompleteDelegate、以及委托的回调函数 OnJoinSessionComplete()

    ...UCLASS(config=Game)
    class AMenuSystemCharacter : public ACharacter
    {GENERATED_BODY()...public:// 会话接口智能指针// IOnlineSessionPtr OnlineSessionInterface;	// 添加头文件 "Interfaces/OnlineSessionInterface.h" 后使用,更具可读性TSharedPtr<class IOnlineSession, ESPMode::ThreadSafe> OnlineSessionInterface;	// 使用 TSharedPtr 智能指针包装器进行声明protected:UFUNCTION(BlueprintCallable)void CreateGameSession();	// 创建游戏会话UFUNCTION(BlueprintCallable)void JoinGameSession();		// 加入游戏会话void OnCreateSessionComplete(FName SessionName, bool bWasSuccessful);	// 委托 CreateSessionCompleteDelegate 的回调函数void OnFindSessionsComplete(bool bWasSuccessful);	// 委托 FindSessionCompleteDelegate 的回调函数/* P13 加入游戏会话(Joining The Sessions)*/void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result);	// 委托 JoinSessionCompleteDelegate 的回调函数/* P13 加入游戏会话(Joining The Sessions)*/private:// 类 FOnCreateSessionCompleteDelegate 在 UE 5.0 和 5.1 版本的头文件 "Interfaces/OnlineSessionInterface.h" 中声明// 而 5.2 和 5.3 版本的头文件 "Interfaces/OnlineSessionDelegates.h" 中声明FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate;	// 会话创建完成委托FOnFindSessionsCompleteDelegate FindSessionsCompleteDelegate;	// 会话查找完成委托TSharedPtr<FOnlineSessionSearch> SessionSearch;					// 会话查找智能指针/* P13 加入游戏会话(Joining The Sessions)*/FOnJoinSessionCompleteDelegate JoinSessionCompleteDelegate;		// 会话加入完成委托/* P13 加入游戏会话(Joining The Sessions)*/
    };
    
  2. 在 “MenuSystemcharacter.cpp” 构造函数 “AMenuSystemCharacter::AMenuSystemCharacter()” 中为委托 “JoinSessionCompleteDelegate” 绑定回调函数 “OnJoinSessionComplete()” ,并在回调函数 “OnFindSessionsComplete()” 中添加 “JoinSessionCompleteDelegate” 到委托列表。

    ...AMenuSystemCharacter::AMenuSystemCharacter() :	// 为委托绑定回调函数CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCreateSessionComplete)),FindSessionsCompleteDelegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnFindSessionsComplete)),/* P13 加入游戏会话(Joining The Sessions)*/ JoinSessionCompleteDelegate(FOnJoinSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnJoinSessionComplete))/* P13 加入游戏会话(Joining The Sessions)*/	
    {...}void AMenuSystemCharacter::OnFindSessionsComplete(bool bWasSuccessful)
    {/* P13 加入游戏会话(Joining The Sessions)*/if (!OnlineSessionInterface.IsValid()) {return;}/* P13 加入游戏会话(Joining The Sessions)*/for (auto Result : SessionSearch->SearchResults) {	// 遍历游戏会话搜索结果FString Id = Result.GetSessionIdStr();FString User = Result.Session.OwningUserName;/* P13 加入游戏会话(Joining The Sessions)*/FString MatchType;	// 保存游戏会话匹配类型Result.Session.SessionSettings.Get(FName("MatchType"), MatchType);	// 获取游戏会话匹配类型保存在 MatchType 中/* P13 加入游戏会话(Joining The Sessions)*/if (GEngine) {GEngine->AddOnScreenDebugMessage(	// 添加调试信息到屏幕上-1,								// 使用 -1 不会覆盖前面的调试信息15.f,							// 调试信息的显示时间FColor::Cyan,					// 字体颜色:蓝绿色FString::Printf(TEXT("Id: %s, User: %s!"), *Id, *User)	// 打印游戏会话匹配类型);}/* P13 加入游戏会话(Joining The Sessions)*/if (MatchType == FString("FreeForAll")) {if (GEngine) {GEngine->AddOnScreenDebugMessage(	// 添加调试信息到屏幕上-1,								// 使用 -1 不会覆盖前面的调试信息15.f,							// 调试信息的显示时间FColor::Cyan,					// 字体颜色:蓝绿色FString::Printf(TEXT("Joining Match Type: %s!"), *MatchType)	// 打印消息);}OnlineSessionInterface->AddOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegate);	// 添加委托到会话接口的委托列表const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();	//获取本地玩家指针// 第一个输入参数类型为 const FUniqueNetId &SearchingPlayerId// 第二个输入参数类型为 Fname SessionName// 第三个输入参数类型为 const FOnlineSessionSearchResult &DesiredSession,这里写 Result 即可OnlineSessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, Result);	// 调用在线接口函数加入会话}	/* P13 加入游戏会话(Joining The Sessions)*/}
    }...
    
  3. . 在回调函数 “OnJoinSessionComplete()” 中获取游戏会话创建源 IP 地址并打印在屏幕上,然后前往关卡 “Lobby”。保存代码并进行编译。

    void AMenuSystemCharacter::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
    {/* P13 加入游戏会话(Joining The Sessions)*/if (!OnlineSessionInterface.IsValid()) {return;}FString Address;	// 保存游戏会话创建源地址if (OnlineSessionInterface->GetResolvedConnectString(NAME_GameSession, Address)) {if (GEngine) {GEngine->AddOnScreenDebugMessage(	// 添加调试信息到屏幕上-1,								// 使用 -1 不会覆盖前面的调试信息15.f,							// 调试信息的显示时间FColor::Yellow,					// 字体颜色:黄色FString::Printf(TEXT("Connect string: %s!"), *Address)	// 打印游戏会话创建源 IP 地址);}}APlayerController* PlayerController = GetGameInstance()->GetFirstLocalPlayerController();	// 获取玩家控制器if (PlayerController) {PlayerController->ClientTravel(Address, ETravelType::TRAVEL_Absolute);	// 客户端传送至关卡 “Lobby”}/* P13 加入游戏会话(Joining The Sessions)*/
    }
    

13.4 进行测试

  1. 将项目打包之后发送到另一台设备上。在设备 1 上运行游戏(保证 Steam 已经运行),按下数字键 “1”,屏幕左上角红色字体显示会话的名称 “Game Session” ,并且当前关卡跳转至 “Lobby”,说明设备 1 创建会话成功。
    在这里插入图片描述

  2. 在设备 2 上运行游戏(保证 Steam 已经运行且登录的账户与设备1 上登录的账号不同),按下数字键 “2”,屏幕左上角蓝绿色字体显示设备 1 上登录到 Steam 的 ID 和用户名以及设备 1 创建的游戏会话匹配类型 “FreeForAll”,黄色字体显示设备 1 的 IP 地址,当前关卡跳转至 “Lobby”,并且可以看到有两个玩家存在,说明设备 2 找到并加入了设备 1 创建的会话中。
    在这里插入图片描述


13.5 Summary

本节课创建了一个 Basic 类型的新关卡 “Lobby”,使得玩家在加入已创建的会话后可以前往该关卡等待其他玩家的加入。接着,在会话设置 “SessionSettings” 中添加了匹配类型指定和检查的代码,确保为游戏会话设置正确的匹配类型。然后,定义委托 “JoinSessionCompleteDelegate” ,为它绑定回调函数 “OnJoinSessionComplete()”,在回调函数 “OnFindSessionsComplete()” 中添加 “JoinSessionCompleteDelegate” 到在线接口委托列表,通过在线接口函数 “GetResolvedConnectString()” 获取游戏会话创建源 IP 地址,使用函数 “ClientTravel()”进行客户端传送至关卡 “Lobby”。最后在两台设备上登录两个不同的 Steam 账号,以进行创建会话和加入会话测试。
在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/680389.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【操作系统】3.操作系统的运行环境

3.操作系统的运行环境 3.1.操作系统的运行机制 计算机系统中&#xff0c;通常CPU执行两种不同性质的程序&#xff1a; 操作系统内核程序 用户自编程序&#xff0c;即系统外层的应用程序&#xff0c;或简称“应用程序” 对操作系统而言&#xff0c;这两种程序的作用不同——前…

贪心算法入门题(算法村第十七关青铜挑战)

青铜挑战&#xff1a;贪心其实很简单 贪心算法&#xff08;贪婪算法&#xff09;是指在对问题进行求解时&#xff0c;在每一步选择中都采取最好或者最优的选择&#xff0c;从而希望能够导致结果是最好或者最优的算法。 贪心算法要么得到最优解&#xff0c;要么得到近似最优解…

手把手教你开发Python桌面应用-PyQt6图书管理系统-修改密码UI设计实现

锋哥原创的PyQt6图书管理系统视频教程&#xff1a; PyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~_哔哩哔哩_bilibiliPyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~共计24条视频&…

Linux第46步_通过“添加自定义菜单”来学习menuconfig图形化配置原理

通过“添加自定义菜单”来学习menuconfig图形化配置原理&#xff0c;将来移植linux要用到。 自定义菜单要求如下: ①、在主界面中添加一个名为“My test menu”&#xff0c;此菜单内部有一个配置项。 ②、配置项为“MY TESTCONFIG”&#xff0c;此配置项处于菜单“My test m…

Spring Security实现权限认证与授权

一、Spring Security Spring Security作为Spring家族的安全框架&#xff0c;在安全方面的两个核心功能是认证&#xff08;Authentication&#xff09;和授权&#xff08;Authorization&#xff09;。 &#xff08;1&#xff09;用户认证指的是&#xff1a;验证某个用户是否为系…

【Java程序设计】【C00265】基于Springboot的地方废物回收机制管理系统(有论文)

基于Springboot的地方废物回收机制管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的地方废物回收机构管理系统 本系统分为管理员功能模块以及员工功能模块。 管理员功能模块&#xff1a;管理员登录系统后…

假期day8多进程与多线程(2024/2/11)

多进程服务器 #include<myhead.h> #define PORT 9999 //端口号 #define IP "192.168.125.113" //IP地址//定义信号处理函数&#xff0c;用于回收僵尸进程 void handler(int signo) {if(signo SIGCHLD){while(waitpid(-1, NULL, WNOH…

EXCEL中如何调出“数据分析”的菜单

今天发现&#xff0c;原来WPS还是和EXCEL比&#xff0c;还是少了“数据分析”这个日常基本做统计的菜单&#xff0c;只好用EXCEL了&#xff0c;但奇怪发现我的EXCEL中没发现这个菜单&#xff0c;然后查了下&#xff0c;才发现&#xff0c;要用如下的方法打开&#xff1a; 1&…

Go+:一种简单而强大的编程语言

Go是一种简单而强大的编程语言&#xff0c;它是在Go语言之上构建的&#xff0c;旨在提供更加强大、灵活和易于使用的编程体验。Go与Go语言共享大部分语法和语义&#xff0c;因此Go开发人员可以很快上手Go&#xff0c;同时也可以使用Go来编写更加简洁和高效的代码。在本文中&…

LeetCode516. Longest Palindromic Subsequence——动态规划

文章目录 一、题目二、题解 一、题目 Given a string s, find the longest palindromic subsequence’s length in s. A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remainin…

STM32自学☞定时器定时中断案例

timer_interrupt.c文件 /* 初始化函数编写步骤&#xff1a; 1.打开时钟 2.选择时基单元的时钟源&#xff08;内部时钟源&#xff09; 3.配置时基单元 4.NVIC配置 5.启动定时器 */ #include "stm32f10x.h" #include "stm32f10x_tim.h" #include …

【数论】exgcd 扩展欧几里得算法

参考&#xff1a;exgcd详解 - zzt1208 - 博客园 (cnblogs.com) exgcd&#xff08;扩展欧几里得算法&#xff09;&#xff0c;用来求形如 a x b y g c d ( a , b ) axbygcd(a,b) axbygcd(a,b)&#xff08; a , b a,b a,b 为常数&#xff09;的方程的一组整数解。&#xff08…

[力扣]编程基础 0 到 1

文章目录 编程基础 0 到 1思路解题方法进行优化 编程基础 0 到 1 【LeetCode】(Python)&#xff1a;1768. 交替合并字符串 思路 给你两个字符串 word1 和 word2 。请你从 word1 开始&#xff0c;通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长&#xff0c;就…

springboot-接入ai机器人 汇总

鱼聪明 Java SDKGitHub - liyupi/yucongming-java-sdk: 鱼聪明 AI 的 Java SDK&#xff0c;几行代码使用 AI 助手能力&#xff01;

CVE-2022-25578 漏洞复现

CVE-2022-25578 路由/admin/admin.php是后台&#xff0c;登录账号和密码默认是admin、tao&#xff0c;选择文件管理。 是否还记得文件上传中的.htaccess配置文件绕过发&#xff0c;在这个文件中加入一句AddType application/x-httpd-php .jpg&#xff0c;将所有jpg文件当作php…

位运算+leetcode(1)

基础 1.基础知识 以下都是针对数字的二进制进行操作 >> 右移操作符<< 左移操作符~ 取反操作符 & 有0就是0&#xff0c;全一才一 | 有一才一 &#xff0c;全0才0^ 相同为0&#xff0c;相异为1 异或( ^ )运算的规律 a ^ 0 a a ^ a 0a ^ b ^ c a ^ (b …

GraphicsMagick 的 OpenCL 开发记录(三十八)

文章目录 AccelerateScaleImage()和AccelerateResizeImage()的性能测试 <2022-05-18 Wed> AccelerateScaleImage()和AccelerateResizeImage()的性能测试 迭代100次&#xff0c;缩小图片50%&#xff0c;如下&#xff1a; [ysouynoarch gm-ocl]$ MAGICK_OCL_DEVICEtrue …

MyBatis篇----第一篇

系列文章目录 文章目录 系列文章目录前言一、什么是 Mybatis?二、Mybaits 的优点三、MyBatis 框架的缺点前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一、什么…

【记录】电容的作用,调试Arduino及ESP8266

最近调试Arduino结合ESP8266进行WIFI传输和云端控制&#xff0c;准备用Arduino的3.3V输出直接作为ESP8266的电源&#xff0c;不想竟掉坑里了。 Arduino的3.3V输出接上ESP8266后&#xff0c;Arduino的程序就跑飞了。ESP8266刚上电还是相当生猛的&#xff0c;要吃掉一百多毫安的…

XBox One 国行解锁

国行机解锁具体步骤&#xff1a; ①&#xff1a;将主机升级到最新版的操作系统 ②&#xff1a;将U盘格式化为NTFS格式。 ③&#xff1a;新建一个文本文档&#xff0c;根据主机型号重命名为&#xff1a; XSX/S&#xff1a;$ConsoleGen9 X1X/S&#xff1a;$ConsoleGen8 X1&…