《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 创建会话

本节课将学习委托(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;		// 会话设置:设置最大公共连接数为 4
    	SessionSettings->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
    																					// 这个包装器重载了引用运算符 *,它表示 * 返回一个引用 *UniquenetId
    										  NAME_GameSession,							// 第二个参数类型为 FName SessionName,游戏会话名称
    										  *SessionSettings);						// 第三个参数类型为 const FOnlineSessionSettings &NewSessionSettings										 	
    }
    /* P10 创建会话(Creating A Session)*/
    
    ...
    

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

  3. 继续在 “MenuSystemCharacter.cpp” 中完成回调函数 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 在视频中是没有提及的,如果在后面的测试出现无法创建会话,则需要添加。


  • 31
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值