《UE5_C++多人TPS完整教程》学习笔记9 ——《P10 创建会话(Creating A Session)》

本文主要是介绍《UE5_C++多人TPS完整教程》学习笔记9 ——《P10 创建会话(Creating A Session)》,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


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


文章目录

  • P10 创建会话
  • 10.1 委托
  • 10.2 创建委托以及回调函数
  • 10.3 Summary


P10 创建会话

本节课将学习委托(Delegates)的基本概念、工作原理以及它对于管理多人游戏的关键(Crucial)作用,然后我们将在上节课《P9 访问 Steam(Acessing Steam)》 代码的基础上,尝试创建一个游戏会话,并通过在屏幕上打印文本来验证游戏会话是否创建成功。
在这里插入图片描述


10.1 委托

  1. 委托可以被认为是一个持有对函数的引用(Reference)的对象。虚幻引擎的委托可以与函数 绑定(Having functions bound to them),可以 广播到 所有与它绑定的函数接收并执行以进行 响应 的信号。我们通常会编写 回调函数(Make functions referred to as callback functions)然后将它们绑定到委托上。于是,当游戏中的某个确定事件(Certain event)发生时,委托被触发或者广播,任何绑定在该委托的 回调函数 都将进行响应。
    在这里插入图片描述

  2. 虚幻引擎的在线会话需要利用委托,这是因为创建和加入游戏会话都需要在互联网上发送信息。如果我们调用 会话接口Session interface)函数 “CreateSession()” 就会发送信息到服务平台(本课程为 Steam),此时游戏会话就能被创建,然后服务平台将(反馈)信息发送到我们的设备上,让我们知道会话创建已经完成。
    会话接口Session interface)定义了一组委托类型,拥有一个可以在适当的时间内通过事件触发进行遍历的 委托列表Delegate list),我们将以其中一个委托类型创建一个新对象,为它绑定一个回调函数,并添加到会话接口的委托列表中。
    在这里插入图片描述

  3. 本节课的思路就是首先利用函数 “FOnCreateSessionCompleteDelegate” 在第三人称游戏项目 MenuSystemcharacter 类中创建委托(变量),同时也创建一个绑定到该委托的回调函数 “OnCreateSessionComplete()”,接着访问会话接口并添加委托到委托列表中;然后调用会话接口函数 “CreateSession()” 连接到 Steam 以创建游戏会话,游戏会话创建完成后 Steam 向会话接口发送一个信号,会话接口将遍历委托列表,从而触发我们添加到此列表的委托并导致回调函数 “OnCreateSessionComplete()” 被调用并接收游戏会话创建完成的信息;通过打印信息到屏幕上,就可以验证会话是否真的创建成功。
    在这里插入图片描述

    关于委托的更多知识可以参阅官方文档《委托》。


10.2 创建委托以及回调函数

  1. 添加代码到 “MenuSystemcharacter.h” 的类 “AMenuSystemCharacter” 中,定义委托 CreateSessionCompleteDelegate、创建游戏会话函数 CreateGameSession() 以及委托的回调函数 OnCreateSessionComplete()

    ...#include "Interfaces/OnlineSessionInterface.h"...UCLASS(config=Game)
    class AMenuSystemCharacter : public ACharacter
    {.../* P10 创建会话(Creating A Session)*/
    public:// 会话接口智能指针// IOnlineSessionPtr OnlineSessionInterface;	// 添加头文件 "Interfaces/OnlineSessionInterface.h" 后使用,更具可读性TSharedPtr<class IOnlineSession, ESPMode::ThreadSafe> OnlineSessionInterface;	// 使用 TSharedPtr 智能指针包装器进行声明protected:UFUNCTION(BlueprintCallable)void CreateGameSession();	// 创建游戏会话void OnCreateSessionComplete(FName SessionName, bool bWasSuccessful);	// 委托 CreateSessionCompleteDelegate 的回调函数private:// 类 FOnCreateSessionCompleteDelegate 在 UE 5.0 和 5.1 版本的头文件 "Interfaces/OnlineSessionInterface.h" 中声明// 而 5.2 和 5.3 版本的头文件 "Interfaces/OnlineSessionDelegates.h" 中声明FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate;	// 会话创建完成委托/* P10 创建会话(Creating A Session)*/	};
    
  2. 在 “MenuSystemcharacter.cpp” 构造函数 “AMenuSystemCharacter::AMenuSystemCharacter()” 中为委托 “CreateSessionCompleteDelegate” 绑定回调函数 “OnCreateSessionComplete()” 并完成创建游戏会话函数 CreateGameSession() 的定义。

    /* MenuSystemcharacter.h */
    ...
    /* P10 创建会话(Creating A Session)*/
    #include "OnlineSessionSettings.h"
    /* P10 创建会话(Creating A Session)*/
    .../* MenuSystemcharacter.cpp */
    .../* P10 创建会话(Creating A Session)*/
    AMenuSystemCharacter::AMenuSystemCharacter():	// 为委托绑定回调函数
    CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCreateSessionComplete))
    /* P10 创建会话(Creating A Session)*/	
    {...}/* P10 创建会话(Creating A Session)*/
    void AMenuSystemCharacter::CreateGameSession()	// 当按下数字键 1 时调用
    {// 检查会话接口是否有效if (!OnlineSessionInterface.IsValid()) {return;}// 检查是否先前存在会话auto ExistingSession = OnlineSessionInterface->GetNamedSession(NAME_GameSession);if (ExistingSession != nullptr) {								// 如果先前存在会话OnlineSessionInterface->DestroySession(NAME_GameSession);	// 销毁会话}OnlineSessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate);	// 添加委托到会话接口的委托列表TSharedPtr<FOnlineSessionSettings> SessionSettings = MakeShareable(new FOnlineSessionSettings());	// 创建会话设置,利用函数 MakeShareable 初始化// FOnlineSessionSettings 在头文件 "OnlineSessionSettings.h" 中// 会话设置成员变量参阅及含义: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)const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();					// 获取本地玩家指针OnlineSessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(),	// 第一个参数类型为 strut FUniqueNetIdRepl,公共继承了 struct FUniqueNetIdWrapper// 这个包装器重载了引用运算符 *,它表示 * 返回一个引用 *UniquenetIdNAME_GameSession,							// 第二个参数类型为 FName SessionName,游戏会话名称*SessionSettings);						// 第三个参数类型为 const FOnlineSessionSettings &NewSessionSettings										 	
    }
    /* P10 创建会话(Creating A Session)*/...
    

    会话设置代码 SessionSettings->bUseLobbiesIfAvailable = true 在视频中是没有提及的,如果在后面的测试出现无法创建会话,则需要添加(作者在下一集教学视频 《P11 设置加入会话(Setup for Joining Sessions)》 中会提到这点)。在这里插入图片描述
    在这里插入图片描述

  3. 继续在 “MenuSystemcharacter.cpp” 构造函数 “AMenuSystemCharacter::AMenuSystemCharacter()” 中完成回调函数 OnCreateSessionComplete() 的定义。

    .../* P10 创建会话(Creating A Session)*/
    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())	// 打印游戏会话的名称);}}else {	// 如果游戏会话创建失败if (GEngine) {		GEngine->AddOnScreenDebugMessage(	// 添加调试信息到屏幕上-1,								// 使用 -1 不会覆盖前面的调试信息15.f,							// 调试信息的显示时间FColor::Red,					// 字体颜色FString::Printf(TEXT("Failed to create session!"))	// 打印失败消息);}}
    }
    /* P10 创建会话(Creating A Session)*/...
    
  4. 进行实时编译,编译成功后打开 “BP_ThirdPersonCharacter” 蓝图编辑器,绘制如下蓝图,编译、保存。
    在这里插入图片描述

  5. 将项目打包之后再运行游戏(保证 Steam 已经运行),按下数字键 “1”,屏幕左上角红色字体显示会话的名称 “Game Session” ,说明创建会话成功。
    在这里插入图片描述


10.3 Summary

本节课学习委托(Delegates)的基本概念、工作原理以及它对于管理多人游戏的关键(crucial)作用,在创建会话的 C++ 编程中,首先利用函数 “FOnCreateSessionCompleteDelegate” 创建委托,接着创建一个绑定到该委托的回调函数 “OnCreateSessionComplete()”,访问会话接口并添加该委托到委托列表中;然后调用会话接口函数 “CreateSession()” 连接到 Steam 以创建游戏会话,游戏会话创建完成后 Steam 向会话接口发送一个信号,会话接口遍历委托列表,触发我们添加到此列表的委托并导致回调函数 “OnCreateSessionComplete()” 被调用,接收游戏会话创建完成的信息,我们将其打印在屏幕上。
在这里插入图片描述

10.1 委托 中,有关委托的进一步学习可以参阅官方文档《委托》。

10.2 创建委托以及回调函数步骤 2 中,会话设置代码 SessionSettings->bUseLobbiesIfAvailable = true 在视频中是没有提及的,如果在后面的测试出现无法创建会话,则需要添加。


这篇关于《UE5_C++多人TPS完整教程》学习笔记9 ——《P10 创建会话(Creating A Session)》的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/703053

相关文章

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

Spring Security中用户名和密码的验证完整流程

《SpringSecurity中用户名和密码的验证完整流程》本文给大家介绍SpringSecurity中用户名和密码的验证完整流程,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定... 首先创建了一个UsernamePasswordAuthenticationTChina编程oken对象,这是S

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

java向微信服务号发送消息的完整步骤实例

《java向微信服务号发送消息的完整步骤实例》:本文主要介绍java向微信服务号发送消息的相关资料,包括申请测试号获取appID/appsecret、关注公众号获取openID、配置消息模板及代码... 目录步骤1. 申请测试系统2. 公众号账号信息3. 关注测试号二维码4. 消息模板接口5. Java测试

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

C++11委托构造函数和继承构造函数的实现

《C++11委托构造函数和继承构造函数的实现》C++引入了委托构造函数和继承构造函数这两个重要的特性,本文主要介绍了C++11委托构造函数和继承构造函数的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、委托构造函数1.1 委托构造函数的定义与作用1.2 委托构造函数的语法1.3 委托构造函

C++11作用域枚举(Scoped Enums)的实现示例

《C++11作用域枚举(ScopedEnums)的实现示例》枚举类型是一种非常实用的工具,C++11标准引入了作用域枚举,也称为强类型枚举,本文主要介绍了C++11作用域枚举(ScopedEnums... 目录一、引言二、传统枚举类型的局限性2.1 命名空间污染2.2 整型提升问题2.3 类型转换问题三、C