《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

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

Ubuntu固定虚拟机ip地址的方法教程

《Ubuntu固定虚拟机ip地址的方法教程》本文详细介绍了如何在Ubuntu虚拟机中固定IP地址,包括检查和编辑`/etc/apt/sources.list`文件、更新网络配置文件以及使用Networ... 1、由于虚拟机网络是桥接,所以ip地址会不停地变化,接下来我们就讲述ip如何固定 2、如果apt安

PyCharm 接入 DeepSeek最新完整教程

《PyCharm接入DeepSeek最新完整教程》文章介绍了DeepSeek-V3模型的性能提升以及如何在PyCharm中接入和使用DeepSeek进行代码开发,本文通过图文并茂的形式给大家介绍的... 目录DeepSeek-V3效果演示创建API Key在PyCharm中下载Continue插件配置Con

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创