UGameFeatureAction 类
这是一个抽象基类,用于定义游戏功能模块激活时需要执行的具体操作。它在 LyraStarterGame 项目中被广泛用于模块化和插件化的游戏功能管理。
GameFeatureAction.h
cpp
// 版权所有 Epic Games, Inc. 保留所有权利。
#pragma once
#include "GameFeatureAction.generated.h"
#define UE_API GAMEFEATURES_API
class UGameFeatureData;
struct FGameFeatureActivatingContext;
struct FGameFeatureDeactivatingContext;
struct FAssetBundleData;
/** 表示游戏功能激活时要执行的操作 */
UCLASS(MinimalAPI, DefaultToInstanced, EditInlineNew, Abstract)
class UGameFeatureAction : public UObject
{
GENERATED_BODY()
public:
UE_API virtual UGameFeatureData* GetGameFeatureData() const;
/** 当拥有此操作的对象被注册以准备激活时调用,即使功能从未激活也会调用 */
virtual void OnGameFeatureRegistering() {}
/** 取消注册操作时调用,除非再次注册,否则不会再次激活 */
virtual void OnGameFeatureUnregistering() {}
/** 表示功能即将被加载以准备激活时调用 */
virtual void OnGameFeatureLoading() {}
/** 表示功能正在被卸载时调用 */
virtual void OnGameFeatureUnloading() {}
/** 当功能实际应用时调用 */
UE_API virtual void OnGameFeatureActivating(FGameFeatureActivatingContext& Context);
/** 旧式无上下文的激活函数,如果未重写带上下文的版本,则由基类调用 */
virtual void OnGameFeatureActivating() {}
/** 当功能完全激活时调用 */
virtual void OnGameFeatureActivated() {}
/** 当游戏功能停用时调用,未来可能再次激活 */
virtual void OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context) {}
/** 返回此操作所属的游戏功能插件是否已注册 */
UE_API bool IsGameFeaturePluginRegistered(bool bCheckForRegistering = false) const;
/** 返回此操作所属的游戏功能插件是否处于活动状态 */
UE_API bool IsGameFeaturePluginActive(bool bCheckForActivating = false) const;
#if WITH_EDITORONLY_DATA
virtual void AddAdditionalAssetBundleData(FAssetBundleData& AssetBundleData) {}
#endif
};
#undef UE_API
GameFeatureAction.cpp
cpp
// 版权所有 Epic Games, Inc. 保留所有权利。
#include "GameFeatureAction.h"
#include "GameFeatureData.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(GameFeatureAction)
/**
* 获取与此操作关联的 GameFeatureData 对象
* 通过遍历外部对象链查找 UGameFeatureData 实例
* @return 找到的 UGameFeatureData 指针,若未找到则返回 nullptr
*/
UGameFeatureData* UGameFeatureAction::GetGameFeatureData() const
{
// 从当前对象的外部对象开始向上遍历
for (UObject* Obj = GetOuter(); Obj; Obj = Obj->GetOuter())
{
// 尝试将外部对象转换为 UGameFeatureData
if (UGameFeatureData* GFD = Cast<UGameFeatureData>(Obj))
{
return GFD; // 找到并返回
}
}
return nullptr; // 未找到
}
/**
* 游戏功能激活时的处理函数(带上下文)
* 如果派生类未重写此函数,则调用旧式的无上下文版本
* @param Context 激活上下文信息
*/
void UGameFeatureAction::OnGameFeatureActivating(FGameFeatureActivatingContext& Context)
{
// 调用旧式无上下文的激活函数(如果派生类未重写此版本)
OnGameFeatureActivating();
}
/**
* 检查此操作所属的游戏功能插件是否已注册
* @param bCheckForRegistering 是否检查正在注册中的状态
* @return 如果已注册(或在注册中,取决于参数)返回 true,否则返回 false
*/
bool UGameFeatureAction::IsGameFeaturePluginRegistered(bool bCheckForRegistering /*= false*/) const
{
// 获取关联的 GameFeatureData
UGameFeatureData* GameFeatureData = GetGameFeatureData();
// 如果存在,则调用其 IsGameFeaturePluginRegistered 方法,否则返回 false
return !!GameFeatureData ? GameFeatureData->IsGameFeaturePluginRegistered(bCheckForRegistering) : false;
}
/**
* 检查此操作所属的游戏功能插件是否处于活动状态
* @param bCheckForActivating 是否检查正在激活中的状态
* @return 如果已激活(或在激活中,取决于参数)返回 true,否则返回 false
*/
bool UGameFeatureAction::IsGameFeaturePluginActive(bool bCheckForActivating /*= false*/) const
{
// 获取关联的 GameFeatureData
UGameFeatureData* GameFeatureData = GetGameFeatureData();
// 如果存在,则调用其 IsGameFeaturePluginActive 方法,否则返回 false
return !!GameFeatureData ? GameFeatureData->IsGameFeaturePluginActive(bCheckForActivating) : false;
}
以下是该类所有成员的分析,包括其作用和在 LyraStarterGame 项目中的典型应用:
成员变量分析
- 类声明(无显式成员变量)
GENERATED_BODY(): 这是一个虚幻引擎的宏,用于自动生成反射系统所需的代码(如序列化、垃圾回收等)。它本身不是函数,但会展开为类实现的一部分。- 应用 :使得所有派生自
UGameFeatureAction的类都能被UE的反射系统识别,从而可以在编辑器属性面板中显示、被蓝图调用、被序列化/反序列化。
成员函数分析
-
virtual UGameFeatureData* GetGameFeatureData() const- 作用 :通过遍历当前对象的
Outer(外部对象)链,向上查找并返回持有此Action的UGameFeatureData父对象。 - Lyra应用 :每个
UGameFeatureAction实例都作为资产内嵌在某个UGameFeatureData资产中。此函数是Action与它的"所属插件"建立联系的桥梁。在Lyra中,当一个功能(如添加新武器、新游戏模式、新技能)需要知道自己是哪个插件的一部分时,就会调用此函数。
- 作用 :通过遍历当前对象的
-
virtual void OnGameFeatureRegistering()- 作用 :当包含此Action的
GameFeatureData被注册到游戏框架时调用。这是生命周期的第一步,即使该功能从未激活也会调用。适用于进行一些一次性、低开销的初始化。 - Lyra应用 :例如,一个用于注册新
GameplayAbility的Action,可以在这里向全局的能力系统注册该能力的类信息,但不生成实例。
- 作用 :当包含此Action的
-
virtual void OnGameFeatureUnregistering()- 作用 :当包含此Action的
GameFeatureData被取消注册时调用。用于清理在OnGameFeatureRegistering中进行的操作。 - Lyra应用:接上例,在这里从全局能力系统中注销先前注册的类信息。
- 作用 :当包含此Action的
-
virtual void OnGameFeatureLoading()- 作用:表示该功能插件即将被激活,正在加载所需资源(如资产包)时调用。这是进入激活流程的信号。
- Lyra应用:可以在这里预加载一些必要的软引用资产,或者显示加载界面提示。
-
virtual void OnGameFeatureUnloading()- 作用:表示该功能插件正在被卸载,资源即将释放时调用。
- Lyra应用 :可以在这里释放
OnGameFeatureLoading中预加载的资源,或者进行状态清理。
-
virtual void OnGameFeatureActivating(FGameFeatureActivatingContext& Context)- 作用 :核心函数 。当功能插件被正式激活,并开始对游戏世界产生影响时调用。参数
Context提供了激活的上下文信息(如目标世界)。如果派生类没有重写这个带上下文的版本,基类实现会自动调用下面的无参数版本。 - Lyra应用 :这是最常被重写的函数。例如:
GameFeatureAction_AddWidget: 在这里为本地玩家创建并添加一个HUD组件。GameFeatureAction_AddComponents: 在这里为符合条件的Actor(通过数据资产配置筛选)动态添加新的组件(如技能系统组件、属性组件)。GameFeatureAction_DataRegistry: 在这里加载并注册一个数据表格到数据注册表中,供游戏内查询(如武器数值、角色属性)。
- 作用 :核心函数 。当功能插件被正式激活,并开始对游戏世界产生影响时调用。参数
-
virtual void OnGameFeatureActivating()- 作用 :旧式的、无上下文的激活函数。为了向后兼容而保留。现代实现应优先重写带
Context的版本。 - Lyra应用:在Lyra中,新的Action类通常不使用此版本,而是使用带上下文的版本,因为它能明确知道在哪个游戏世界激活(客户端/服务器、主世界/流式世界)。
- 作用 :旧式的、无上下文的激活函数。为了向后兼容而保留。现代实现应优先重写带
-
virtual void OnGameFeatureActivated()- 作用:当功能插件完全激活并准备就绪后调用。标志着激活流程的完成。
- Lyra应用 :可以在这里执行一些激活完成后才能做的操作,例如广播一个事件通知其他系统"某个新武器类型已可用",或者与刚刚在
OnGameFeatureActivating中添加的组件进行初始交互。
-
virtual void OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context)- 作用 :当功能插件被停用时调用。用于撤销
OnGameFeatureActivating中所做的所有更改。参数Context提供了停用的上下文。 - Lyra应用 :这是清理的核心位置。例如:
- 移除已添加的HUD组件。
- 销毁已动态添加的Actor组件。
- 从数据注册表中注销已添加的数据。
- 作用 :当功能插件被停用时调用。用于撤销
-
bool IsGameFeaturePluginRegistered(bool bCheckForRegistering = false) const- 作用 :查询此Action所属的插件是否已注册到引擎。参数
bCheckForRegistering为true时,正在注册中的状态也返回true。 - Lyra应用:用于在Action内部逻辑中进行条件判断,例如"只有插件已注册时才允许执行某些初始化代码",避免在错误的状态下执行操作。
- 作用 :查询此Action所属的插件是否已注册到引擎。参数
-
bool IsGameFeaturePluginActive(bool bCheckForActivating = false) const- 作用 :查询此Action所属的插件是否处于活动状态。参数
bCheckForActivating为true时,正在激活中的状态也返回true。 - Lyra应用:用于Action内部或外部系统进行状态检查。例如,一个游戏系统在运行时可能需要判断"某某武器插件是否已激活",来决定是否生成该武器或显示相关UI。
- 作用 :查询此Action所属的插件是否处于活动状态。参数
-
virtual void AddAdditionalAssetBundleData(FAssetBundleData& AssetBundleData)- 作用 :(仅编辑器模式)允许Action向它所属的
UGameFeatureData资产添加额外的资产引用,这些引用会被打包到该插件的资产包中。用于声明性的依赖管理。 - Lyra应用 :如果一个
GameFeatureAction需要用到某个特定的材质或声音资产,它可以在这个函数中将这些资产的引用添加到AssetBundleData。这样,当插件被打包时,这些资产会被自动包含进去,确保运行时能正确加载,无需手动管理依赖。
- 作用 :(仅编辑器模式)允许Action向它所属的
总结与Lyra项目的架构关系
在 LyraStarterGame 项目中:
UGameFeatureData是一个资产,代表一个可插拔的游戏功能模块(如"突击步枪包"、"团队死斗模式")。- 一个
UGameFeatureData资产内部包含一个UGameFeatureAction对象的数组。 UGameFeatureAction是这个架构中的 "可执行单元"。每个具体的派生Action负责一项具体的、可复用的事务(添加组件、添加输入、注册数据等)。- Lyra 通过组合不同的
UGameFeatureAction到一个UGameFeatureData中,来定义一个完整功能模块的具体行为。这种设计实现了高度的解耦 和可配置性,使得添加新功能就像在数据资产中勾选和配置几个Action一样简单,无需修改核心C++代码。