Lyra学习5:GameFeatureAction分析

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 项目中的典型应用:

成员变量分析

  1. 类声明(无显式成员变量)
    • GENERATED_BODY(): 这是一个虚幻引擎的宏,用于自动生成反射系统所需的代码(如序列化、垃圾回收等)。它本身不是函数,但会展开为类实现的一部分。
    • 应用 :使得所有派生自 UGameFeatureAction 的类都能被UE的反射系统识别,从而可以在编辑器属性面板中显示、被蓝图调用、被序列化/反序列化。

成员函数分析

  1. virtual UGameFeatureData* GetGameFeatureData() const

    • 作用 :通过遍历当前对象的 Outer(外部对象)链,向上查找并返回持有此Action的 UGameFeatureData 父对象。
    • Lyra应用 :每个 UGameFeatureAction 实例都作为资产内嵌在某个 UGameFeatureData 资产中。此函数是Action与它的"所属插件"建立联系的桥梁。在Lyra中,当一个功能(如添加新武器、新游戏模式、新技能)需要知道自己是哪个插件的一部分时,就会调用此函数。
  2. virtual void OnGameFeatureRegistering()

    • 作用 :当包含此Action的 GameFeatureData 被注册到游戏框架时调用。这是生命周期的第一步,即使该功能从未激活也会调用。适用于进行一些一次性、低开销的初始化。
    • Lyra应用 :例如,一个用于注册新 GameplayAbility 的Action,可以在这里向全局的能力系统注册该能力的类信息,但不生成实例。
  3. virtual void OnGameFeatureUnregistering()

    • 作用 :当包含此Action的 GameFeatureData 被取消注册时调用。用于清理在 OnGameFeatureRegistering 中进行的操作。
    • Lyra应用:接上例,在这里从全局能力系统中注销先前注册的类信息。
  4. virtual void OnGameFeatureLoading()

    • 作用:表示该功能插件即将被激活,正在加载所需资源(如资产包)时调用。这是进入激活流程的信号。
    • Lyra应用:可以在这里预加载一些必要的软引用资产,或者显示加载界面提示。
  5. virtual void OnGameFeatureUnloading()

    • 作用:表示该功能插件正在被卸载,资源即将释放时调用。
    • Lyra应用 :可以在这里释放 OnGameFeatureLoading 中预加载的资源,或者进行状态清理。
  6. virtual void OnGameFeatureActivating(FGameFeatureActivatingContext& Context)

    • 作用核心函数 。当功能插件被正式激活,并开始对游戏世界产生影响时调用。参数 Context 提供了激活的上下文信息(如目标世界)。如果派生类没有重写这个带上下文的版本,基类实现会自动调用下面的无参数版本。
    • Lyra应用 :这是最常被重写的函数。例如:
      • GameFeatureAction_AddWidget: 在这里为本地玩家创建并添加一个HUD组件。
      • GameFeatureAction_AddComponents: 在这里为符合条件的Actor(通过数据资产配置筛选)动态添加新的组件(如技能系统组件、属性组件)。
      • GameFeatureAction_DataRegistry: 在这里加载并注册一个数据表格到数据注册表中,供游戏内查询(如武器数值、角色属性)。
  7. virtual void OnGameFeatureActivating()

    • 作用 :旧式的、无上下文的激活函数。为了向后兼容而保留。现代实现应优先重写带 Context 的版本。
    • Lyra应用:在Lyra中,新的Action类通常不使用此版本,而是使用带上下文的版本,因为它能明确知道在哪个游戏世界激活(客户端/服务器、主世界/流式世界)。
  8. virtual void OnGameFeatureActivated()

    • 作用:当功能插件完全激活并准备就绪后调用。标志着激活流程的完成。
    • Lyra应用 :可以在这里执行一些激活完成后才能做的操作,例如广播一个事件通知其他系统"某个新武器类型已可用",或者与刚刚在 OnGameFeatureActivating 中添加的组件进行初始交互。
  9. virtual void OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context)

    • 作用 :当功能插件被停用时调用。用于撤销 OnGameFeatureActivating 中所做的所有更改。参数 Context 提供了停用的上下文。
    • Lyra应用 :这是清理的核心位置。例如:
      • 移除已添加的HUD组件。
      • 销毁已动态添加的Actor组件。
      • 从数据注册表中注销已添加的数据。
  10. bool IsGameFeaturePluginRegistered(bool bCheckForRegistering = false) const

    • 作用 :查询此Action所属的插件是否已注册到引擎。参数 bCheckForRegistering 为true时,正在注册中的状态也返回true。
    • Lyra应用:用于在Action内部逻辑中进行条件判断,例如"只有插件已注册时才允许执行某些初始化代码",避免在错误的状态下执行操作。
  11. bool IsGameFeaturePluginActive(bool bCheckForActivating = false) const

    • 作用 :查询此Action所属的插件是否处于活动状态。参数 bCheckForActivating 为true时,正在激活中的状态也返回true。
    • Lyra应用:用于Action内部或外部系统进行状态检查。例如,一个游戏系统在运行时可能需要判断"某某武器插件是否已激活",来决定是否生成该武器或显示相关UI。
  12. virtual void AddAdditionalAssetBundleData(FAssetBundleData& AssetBundleData)

    • 作用 :(仅编辑器模式)允许Action向它所属的 UGameFeatureData 资产添加额外的资产引用,这些引用会被打包到该插件的资产包中。用于声明性的依赖管理。
    • Lyra应用 :如果一个 GameFeatureAction 需要用到某个特定的材质或声音资产,它可以在这个函数中将这些资产的引用添加到 AssetBundleData。这样,当插件被打包时,这些资产会被自动包含进去,确保运行时能正确加载,无需手动管理依赖。

总结与Lyra项目的架构关系

在 LyraStarterGame 项目中:

  • UGameFeatureData 是一个资产,代表一个可插拔的游戏功能模块(如"突击步枪包"、"团队死斗模式")。
  • 一个 UGameFeatureData 资产内部包含一个 UGameFeatureAction 对象的数组。
  • UGameFeatureAction 是这个架构中的 "可执行单元"。每个具体的派生Action负责一项具体的、可复用的事务(添加组件、添加输入、注册数据等)。
  • Lyra 通过组合不同的 UGameFeatureAction 到一个 UGameFeatureData 中,来定义一个完整功能模块的具体行为。这种设计实现了高度的解耦可配置性,使得添加新功能就像在数据资产中勾选和配置几个Action一样简单,无需修改核心C++代码。
相关推荐
xrn199728 分钟前
Android OpenCV SDK 编译教程(WSL2 Ubuntu 22.04 环境)
android·c++·opencv
随风一样自由28 分钟前
React内逐行解释这个 package.json 文件,最近搞了个工厂AI生产平台,顺便来学习一下
学习·react.js·json·package
YJlio30 分钟前
Autologon 学习笔记(9.13):安全启用“自动登录”的边界、风险与替代方案
笔记·学习·安全
青衫码上行31 分钟前
【JavaWeb 学习 | 第16篇】JPS介绍和基本语法
java·学习·web·jsp
Blossom.11831 分钟前
基于扩散模型的视频生成优化:从Stable Diffusion到AnimateDiff的显存革命
人工智能·深度学习·学习·决策树·搜索引擎·stable diffusion·音视频
curry____30332 分钟前
study in Dev-c++(string insert基本用法)(2025.12.2)
c++·string·insert
nono牛33 分钟前
C++ 语言全面教程 (基础入门)
java·jvm·c++
冬夜戏雪33 分钟前
【Java学习日记】【2025.12.2】【2/60】
java·开发语言·学习
小年糕是糕手36 分钟前
【C++同步练习】类和对象(一)
java·开发语言·javascript·数据结构·c++·算法·排序算法