本文为B站系列教学视频 《UE5_C++多人TPS完整教程》 —— 《P15 创建我们自己的子系统(Creating Our Own Subsystem)》 的学习笔记,该系列教学视频为 Udemy 课程 《Unreal Engine 5 C++ Multiplayer Shooter》 的中文字幕翻译版,UP主(也是译者)为 游戏引擎能吃么。
文章目录
- P15 创建在线子系统
- 15.1 游戏实例和游戏实例子系统
- 15.2 创建游戏实例子系统类
- 15.3 Summary
P15 创建在线子系统
本节课将尝试创建我们自己的子系统类,并进一步探讨游戏实例子系统类的基本概念、工作原理及方式。
15.1 游戏实例和游戏实例子系统
- 在创建处理多人游戏会话的新类时,一个基本问题就是如何选择这个新类的父类。其中,一个不错的选择(Pretty option)就是游戏实例类:我们的游戏实例在游戏创建时生成,在游戏关闭之前它是不会被销毁的,当我们在关卡之间跳转时也持续存在。然而创建游戏实例类的主要功能并不是管理多人游戏会话(毕竟在前几课中我们在第三人称角色类也可以做到)。
- 游戏实例子系统类和游戏实例类相似,它可以和游戏实例类共存(Coexist along with)。我们可以在游戏实例子系统类中独立处理与多人游戏会话相关的功能。所以这里的重点是在游戏是里创建完成后创建一个游戏实例子系统类,在游戏实例关闭时将其销毁并进行垃圾回收。
虚幻引擎(UE) 中的子系统是生命周期受控(Managed lifetimes)的自动实例化类(Automatically instanced classes)。这些类提供了易用的扩展点(Extension points),程序员可直接获得蓝图和 Python 公开(Exposure),同时避免繁复的引擎类修改或覆盖(Avoiding the complexity of modifying or overriding engine class)。
当前支持的子系统生命周期包括:子系统 继承自 引擎 UEngineSubsystem
类编辑器 UEditorSubsystem
类游戏实例 UGameInstanceSubsystem
类本地玩家 ULocalPlayerSubsystem
类举例而言,如果创建了一个派生自此基类的类:
class UMyGamesSubsystem : public UGameInstanceSubsystem
将出现以下结果:
① 创建UGameInstance
之后,还会创建一个名为UMyGamesSubsystem
的实例。
②UGameInstance
初始化时,将在子系统上调用Initialize()
。
③UGameInstance
关闭时,将在子系统上调用Deinitialize()
。
④ 此时将放弃(Dropped)对子系统的引用,如果不再有对子系统的引用,则其将被垃圾回收(Garbage-collected)。
使用编程子系统有以下几个原因:
- 子系统可节省编程时间。
- 子系统使您无需覆盖引擎类。
- 子系统使您无需在已经很复杂(Busy)的类上添加更多 API 。
- 子系统使您能通过用户友好的类型化节点(User friendly typed nodes)来访问蓝图。
- 子系统允许访问 Python 脚本来编写编辑器脚本或编写测试代码。
- 子系统在代码库中提供模块化和一致性(Modularity and consistency)。
子系统在创建插件时尤为实用。您不需要代码相关的说明即可让插件工作。用户只需将插件添加到游戏中,就可以确切了解插件将在何时被实例化和初始化。因此,您可以专注于UE4中提供的API和功能的使用方式。
GameInstance子系统
class UMyGameSubsystem : public UGameInstanceSubsystem { ... };
这些子系统可通过
UGameInstance
访问,如下所示。UGameInstance* GameInstance = ...; UMyGameSubsystem* MySubsystem = GameInstance->GetSubsystem<UMyGameSubsystem>();
—— 虚幻引擎官方文档《编程子系统》
15.2 创建游戏实例子系统类
- 在虚幻引擎内容浏览器中展开目录 “C++类\MenuSystem”,添加一个新的游戏实例子系统 C++ 类。
- 将新添加的游戏实例子系统 C++ 类命名为 “
MultiplayerSessionsSubsystem
”,选择模块为我们上节课新建的插件 “MultiplayerSessions (Runtime)
”。
- 点击 “创建类” 按钮,VS 中出现弹窗,选择 “全部重新加载(A)”。
-
VS 中可以看到解决方案资源管理器出现了头文件 “
MultiplayerSessionsSubsystem.h
” 和源文件 “MultiplayerSessionsSubsystem.cpp
”;在虚幻引擎的内容浏览器中展开目录 “Plugins/MultiplayerSessionsC++类/MultiplayerSessions/Public
” 也可以看到新建的游戏实例子系统 C++ 类 “MultiplayerSessionsSubsystem
”(如果没看到,可能的解决办法是关闭虚幻引擎然后在 VS 中重新生成解决方案)。
-
在 “
MultiplayerSessionsSubsystem.h
” 中添加代码,定义游戏实例子系统类构造函数 “UMultiplayerSessionSubsystem()
” 和在线会话接口智能指针 “SessionInterface
”。// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Subsystems/GameInstanceSubsystem.h" /* P15 创建我们自己的子系统 */ #include "Interfaces/OnlineSessionInterface.h" #include "OnlineSubsystem.h" /* P15 创建我们自己的子系统 */ #include "MultiplayerSessionsSubsystem.generated.h" /** * */ UCLASS() class MULTIPLAYERSESSIONS_API UMultiplayerSessionsSubsystem : public UGameInstanceSubsystem { GENERATED_BODY() /* P15 创建我们自己的子系统 */ public: UMultiplayerSessionsSubsystem(); protected: private: // 会话接口智能指针 IOnlineSessionPtr OnlineSessionInterface; // 添加头文件 "Interfaces/OnlineSessionInterface.h" 后使用,更具可读性 // TSharedPtr<class IOnlineSession, ESPMode::ThreadSafe> OnlineSessionInterface; // 使用 TSharedPtr 智能指针包装器进行声明 /* P15 创建我们自己的子系统 */ };
-
在 “
MultiplayerSessionsSubsystem.cpp
” 中完善构造函数 “UMultiplayerSessionSubsystem()
”,进行编译。// Fill out your copyright notice in the Description page of Project Settings. #include "MultiplayerSessionsSubsystem.h" /* P15 创建我们自己的子系统 */ UMultiplayerSessionsSubsystem::UMultiplayerSessionsSubsystem() { IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get(); // 获取当前的在线子系统指针 if (OnlineSubsystem) { // 如果当前在线子系统有效 OnlineSessionInterface = OnlineSubsystem->GetSessionInterface(); // 获取会话接口智能指针 } } /* P15 创建我们自己的子系统 */
15.3 Summary
本节课探讨游戏实例类和游戏实例子系统类的基本概念、工作原理及方式,新建了我们自己的游戏实例子系统 C++ 类 “MultiplayerSessionsSubsystem
”,并为该类定义在线会话接口智能指针 “SessionInterface
”、完善了游戏实例子系统类构造函数 “UMultiplayerSessionSubsystem()
” 。