虚幻GameAbilitySystem源码与设计解析-GameEffect中的结构体

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "UObject/Object.h"
#include "UObject/Class.h"
#include "Templates/SubclassOf.h"
#include "Engine/NetSerialization.h"
#include "Engine/EngineTypes.h"
#include "GameplayTagContainer.h"
#include "Engine/CurveTable.h"
#include "AttributeSet.h"
#include "EngineDefines.h"
#include "GameplayEffectTypes.h"
#include "GameplayEffectAggregator.h"
#include "GameplayPrediction.h"
#include "GameplayTagAssetInterface.h"
#include "GameplayAbilitySpec.h"
#include "ActiveGameplayEffectIterator.h"
#include "UObject/ObjectKey.h"
#include "VisualLogger/VisualLoggerDebugSnapshotInterface.h"
#include "VisualLogger/VisualLoggerTypes.h"
屁用没有的头文件

第一个结构体

似乎是用于设置编辑器中的计算方式,常用

 1 UENUM()
 2 enum class EGameplayEffectMagnitudeCalculation : uint8
 3 {
 4     //预先设置好的固定数值。
 5     ScalableFloat,
 6     //基于属性执行计算
 7     AttributeBased,
 8     //执行自定义计算,能够在蓝图(BP)或原生代码中捕捉并作用于多个属性。
 9     CustomCalculationClass,    
10     //此数值将由创建该规格的代码 / 蓝图显式设置。
11     SetByCaller,
12 };
EGameplayEffectMagnitudeCalculation

第二个结构体

 

 1 /** 概述可能的基于属性的浮点数计算策略的枚举。 */
 2 UENUM()
 3 enum class EAttributeBasedFloatCalculationType : uint8
 4 {
 5     /** 使用属性最终计算得出的数值。 */
 6     AttributeMagnitude,
 7     /** 使用属性的基础值。 */
 8     AttributeBaseValue,
 9     /** 使用属性的“额外”计算数值:等同于(最终数值 - 基础值)。 */
10     AttributeBonusMagnitude,
11     /** 使用计算得出的数值,计算截止到指定的“最终通道”评估环节。 */
12     AttributeMagnitudeEvaluatedUpToChannel
13 };
EAttributeBasedFloatCalculationType

第三个结构体

 1 UENUM()
 2 enum class EGameplayEffectVersion : uint8
 3 {
 4     //// 虚幻引擎 5.3 之前的旧版本(在我们开始进行版本管理之前)
 5     Monolithic,    
 6     // 虚幻引擎 5.3 中可用的新模块化版本
 7     Modular53,    
 8     // 授予的能力被移至能力组件中
 9     AbilitiesComponent53,    
10     // 当前版本 = 能力组件 5.3 版本
11     Current = AbilitiesComponent53
12 };
EGameplayEffectVersion(没用,只是对版本做兼容)

第四个结构体

 1 struct GAMEPLAYABILITIES_API FGameplayEffectConstants
 2 {
 3     /** 无限持续时间 */
 4     static const float INFINITE_DURATION;
 5 
 6     /** 无持续时间;表示效果立即应用的时间 */
 7     static const float INSTANT_APPLICATION;
 8 
 9     /** 常量,指定战斗效果没有周期,并且不检查随时间的应用情况 */
10     static const float NO_PERIOD;
11 
12     /** 无效等级/等级未设置 */
13     static const float INVALID_LEVEL;
14 };
FGameplayEffectConstants(设置持续时间)

第五个结构体

FAttributeBasedFloat 结构体用于表示一个基于属性的浮点数,其数值大小由一个关联属性和特定的计算策略共同决定。这种设计在游戏开发中非常有用,例如可以根据角色的某个属性(如攻击力、防御力等)来动态计算一个数值(如伤害值、减伤比例等)。

/** 
 * 结构体表示一个浮点数,其数值大小由一个关联属性和一种计算策略决定,基本形式如下:
 * (系数 * (乘法前累加值 + [根据策略计算得出的属性值])) + 乘法后累加值
 */
USTRUCT()
struct FAttributeBasedFloat
{
    GENERATED_USTRUCT_BODY()

public:

    /** 构造函数 */
    FAttributeBasedFloat()
        : 系数(1.0f)
        , 乘法前累加值(0.0f)
        , 乘法后累加值(0.0f)
        , 关联属性()
        , 属性计算类型(EAttributeBasedFloatCalculationType::AttributeMagnitude)
        , 最终通道(EGameplayModEvaluationChannel::Channel0)
    {}

    /**
     * 根据指定的游戏玩法效果规格计算并返回该浮点数的数值大小。
     * 
     * @注意: 此函数假设(并通过断言检查)规格中存在所需的捕获属性。
     *        调用者有责任在调用此函数之前验证规格是否已正确设置。
     * 
     * @param InRelevantSpec 提供关联属性捕获的游戏玩法效果规格
     * 
     * @return 根据规格和计算策略计算得出的数值
     */
    float CalculateMagnitude(const FGameplayEffectSpec& InRelevantSpec) const;

    /** 属性计算的系数 */
    UPROPERTY(EditDefaultsOnly, Category=AttributeFloat)
    FScalableFloat 系数;

    /** 属性计算的累加值,在系数应用之前添加 */
    UPROPERTY(EditDefaultsOnly, Category=AttributeFloat)
    FScalableFloat 乘法前累加值;

    /** 属性计算的累加值,在系数应用之后添加 */
    UPROPERTY(EditDefaultsOnly, Category=AttributeFloat)
    FScalableFloat 乘法后累加值;

    /** 作为计算基础的属性 */
    UPROPERTY(EditDefaultsOnly, Category=AttributeFloat)
    FGameplayEffectAttributeCaptureDefinition 关联属性;

    /** 如果指定了曲线表条目,属性将用于在曲线中查找值,而不是直接使用属性值。 */
    UPROPERTY(EditDefaultsOnly, Category=AttributeFloat)
    FCurveTableRowHandle 属性曲线;

    /** 关于属性的计算策略 */
    UPROPERTY(EditDefaultsOnly, Category=AttributeFloat)
    EAttributeBasedFloatCalculationType 属性计算类型;

    /** 当使用 AttributeEvaluatedUpToChannel 计算类型时,用于终止评估的通道 */
    UPROPERTY(EditDefaultsOnly, Category=AttributeFloat)
    EGameplayModEvaluationChannel 最终通道;

    /** 用于源标签的过滤器;如果指定,只有带有所有这些标签的修饰符才会纳入计算 */
    UPROPERTY(EditDefaultsOnly, Category=AttributeFloat)
    FGameplayTagContainer 源标签过滤器;

    /** 用于目标标签的过滤器;如果指定,只有带有所有这些标签的修饰符才会纳入计算 */
    UPROPERTY(EditDefaultsOnly, Category=AttributeFloat)
    FGameplayTagContainer 目标标签过滤器;

    /** 相等/不相等运算符 */
    bool operator==(const FAttributeBasedFloat& Other) const;
    bool operator!=(const FAttributeBasedFloat& Other) const;
};
FAttributeBasedFloat(计算方式)

默认值 这个在菜单中很常见,实际上是菜单中的选项

FAttributeBasedFloat()
    : Coefficient(1.f)
    , PreMultiplyAdditiveValue(0.f)
    , PostMultiplyAdditiveValue(0.f)
    , BackingAttribute()
    , AttributeCalculationType(EAttributeBasedFloatCalculationType::AttributeMagnitude)
    , FinalChannel(EGameplayModEvaluationChannel::Channel0)
{}
属性成员
    • Coefficient:属性计算的系数,类型为 FScalableFloat,可以在编辑器中进行编辑。
    • PreMultiplyAdditiveValue:乘法前的累加值,在系数应用之前添加到属性值上。
    • PostMultiplyAdditiveValue:乘法后的累加值,在系数应用之后添加到计算结果上。
    • BackingAttribute:作为计算基础的属性,通过 FGameplayEffectAttributeCaptureDefinition 定义。
    • AttributeCurve:如果指定了曲线表条目,属性将用于在曲线中查找值,而不是直接使用属性值。
    • AttributeCalculationType:指定属性的计算策略,类型为 EAttributeBasedFloatCalculationType 枚举。
    • FinalChannel:当使用 AttributeEvaluatedUpToChannel 计算类型时,用于终止评估的通道,类型为 EGameplayModEvaluationChannel 枚举。
    • SourceTagFilter:用于源标签的过滤器,只有带有所有这些标签的修饰符才会纳入计算。
    • TargetTagFilter:用于目标标签的过滤器,只有带有所有这些标签的修饰符才会纳入计算。
重载了相等和不相等运算符,用于比较两个 FAttributeBasedFloat 结构体是否相等。

bool
operator==(const FAttributeBasedFloat& Other) const; bool operator!=(const FAttributeBasedFloat& Other) const;
第六个结构体
/** 用于封装通过自定义计算得出数值的结构体 */
USTRUCT()
struct FCustomCalculationBasedFloat
{
    GENERATED_USTRUCT_BODY()

    FCustomCalculationBasedFloat()
        : 计算类数值(nullptr)
        , 系数(1.0f)
        , 乘法前累加值(0.0f)
        , 乘法后累加值(0.0f)
    {}

public:

    /**
     * 根据指定的游戏玩法效果规格计算并返回该浮点数的数值。
     * 
     * @注意: 此函数假设(并通过断言检查)规格中存在所需的捕获属性。
     *        调用者有责任在调用此函数之前验证规格是否已正确设置。
     * 
     * @param InRelevantSpec 提供关联属性捕获的游戏玩法效果规格
     * 
     * @return 根据规格和计算策略计算得出的数值
     */
    float CalculateMagnitude(const FGameplayEffectSpec& InRelevantSpec) const;

    /** 自定义计算类,在编辑器中仅可编辑一次,属于自定义计算类别,显示名称为“计算类” */
    UPROPERTY(EditDefaultsOnly, Category=CustomCalculation, DisplayName="Calculation Class")
    TSubclassOf<UGameplayModMagnitudeCalculation> 计算类数值;

    /** 自定义计算的系数 */
    UPROPERTY(EditDefaultsOnly, Category=CustomCalculation)
    FScalableFloat 系数;

    /** 属性计算的累加值,在系数应用之前添加 */
    UPROPERTY(EditDefaultsOnly, Category=CustomCalculation)
    FScalableFloat 乘法前累加值;

    /** 属性计算的累加值,在系数应用之后添加 */
    UPROPERTY(EditDefaultsOnly, Category=CustomCalculation)
    FScalableFloat 乘法后累加值;

    /** 如果指定了曲线表条目,该自定义类计算得出的数值(包括乘法前后的累加值)将用于在曲线中查找,而不是直接使用该数值。 */
    UPROPERTY(EditDefaultsOnly, Category=CustomCalculation)
    FCurveTableRowHandle 最终查找曲线;

    /** 相等/不相等运算符 */
    bool operator==(const FCustomCalculationBasedFloat& Other) const;
    bool operator!=(const FCustomCalculationBasedFloat& Other) const;
};
FCustomCalculationBasedFloat(Cal方法计算)

初始化成员默认值

FCustomCalculationBasedFloat()
    : CalculationClassMagnitude(nullptr)
    , Coefficient(1.f)
    , PreMultiplyAdditiveValue(0.f)
    , PostMultiplyAdditiveValue(0.f)
{}
CalculateMagnitude 方法

该方法根据传入的 FGameplayEffectSpec 规格来计算并返回浮点数的数值。需要注意的是,调用者要确保规格中包含了所需的捕获属性,因为该函数假设并会检查这些属性的存在。

float CalculateMagnitude(const FGameplayEffectSpec& InRelevantSpec) const;
属性成员
    • CalculationClassMagnitude:这是一个指向 UGameplayModMagnitudeCalculation 类的子类的指针,用于指定自定义计算类。开发者可以在编辑器中设置这个类,该类中会实现具体的自定义计算逻辑。
    • Coefficient:自定义计算的系数,类型为 FScalableFloat,可在编辑器中编辑。这个系数会作用于自定义计算的结果。
    • PreMultiplyAdditiveValue:乘法前的累加值,在系数应用之前添加到自定义计算的结果上。
    • PostMultiplyAdditiveValue:乘法后的累加值,在系数应用之后添加到计算结果上。
    • FinalLookupCurve:如果指定了曲线表条目,自定义计算得出的最终数值(包含乘法前后的累加值)会用于在曲线中查找,而不是直接使用该数值,这可以进一步对计算结果进行调整。
 重载了相等和不相等运算符,用于比较两个 FCustomCalculationBasedFloat 结构体是否相等,方便在代码中进行结构体的比较操作。
bool operator==(const FCustomCalculationBasedFloat& Other) const;
bool operator!=(const FCustomCalculationBasedFloat& Other) const;

 

第七个结构体

FSetByCallerFloat 结构体用于存储那些由调用者(可以是代码或者蓝图)来设置具体数值的数据相关信息。在游戏开发里,有时需要让外部调用者动态地为某些数据赋予特定值,这个结构体就提供了一种方式来管理这些数据的标识和相关标签。

/** 用于保存由调用者设置数据的结构体 */
USTRUCT()
struct FSetByCallerFloat
{
    GENERATED_USTRUCT_BODY()

    FSetByCallerFloat()
        : DataName(NAME_None)
    {}

    /** 调用者(代码或蓝图)用于设置此数值大小的名称。 */
    UPROPERTY(VisibleDefaultsOnly, Category=SetByCaller)
    FName DataName;

    /** 在编辑器中仅可编辑一次,属于 SetByCaller 类别,元数据指定标签类别为 "SetByCaller" */
    UPROPERTY(EditDefaultsOnly, Category = SetByCaller, meta = (Categories = "SetByCaller"))
    FGameplayTag DataTag;

    /** 相等/不相等运算符 */
    bool operator==(const FSetByCallerFloat& Other) const;
    bool operator!=(const FSetByCallerFloat& Other) const;
};
FSetByCallerFloat(SetByCaller)

构造函数对结构体的 DataName 成员进行初始化,将其设置为 NAME_None,这是 FName 类型的一个特殊值,表示空名称。

FSetByCallerFloat()
    : DataName(NAME_None)
{}
  • DataName:这是一个 FName 类型的成员,它是调用者用来设置该数据数值大小的名称。VisibleDefaultsOnly 表明这个属性在编辑器中只能查看默认值,不能进行修改。通过这个名称,调用者可以准确地指定要设置哪个数据。
  • DataTag:这是一个 FGameplayTag 类型的成员,可在编辑器中仅编辑一次。meta = (Categories = "SetByCaller") 是元数据设置,指定该标签属于 "SetByCaller" 类别。游戏玩法标签通常用于对游戏中的各种元素进行分类和标识,这里的数据标签可以用来进一步区分和筛选这些由调用者设置的数据。
bool operator==(const FSetByCallerFloat& Other) const;
bool operator!=(const FSetByCallerFloat& Other) const;

重载了相等和不相等运算符,用于比较两个 FSetByCallerFloat 结构体是否相等。这样在代码中就可以方便地判断两个此类结构体是否具有相同的 DataName 和 DataTag 等内容。

 

第八个结构体

/** 结构体表示游戏玩法效果修饰符的数值大小,可能通过多种不同方式计算得出 */
USTRUCT()
struct GAMEPLAYABILITIES_API FGameplayEffectModifierMagnitude
{
    GENERATED_USTRUCT_BODY()

public:

    /** 默认构造函数 */
    FGameplayEffectModifierMagnitude()
        : MagnitudeCalculationType(EGameplayEffectMagnitudeCalculation::ScalableFloat)
    {
    }

    /** 在代码中设置值的构造函数(用于自动化测试) */
    FGameplayEffectModifierMagnitude(const FScalableFloat& Value)
        : MagnitudeCalculationType(EGameplayEffectMagnitudeCalculation::ScalableFloat)
        ,ScalableFloatMagnitude(Value)
    {
    }
    FGameplayEffectModifierMagnitude(const FAttributeBasedFloat& Value)
        : MagnitudeCalculationType(EGameplayEffectMagnitudeCalculation::AttributeBased)
        , AttributeBasedMagnitude(Value)
    {
    }
    FGameplayEffectModifierMagnitude(const FCustomCalculationBasedFloat& Value)
        : MagnitudeCalculationType(EGameplayEffectMagnitudeCalculation::CustomCalculationClass)
        , CustomMagnitude(Value)
    {
    }
    FGameplayEffectModifierMagnitude(const FSetByCallerFloat& Value)
        : MagnitudeCalculationType(EGameplayEffectMagnitudeCalculation::SetByCaller)
        , FSetByCallerFloat(Value)
    {
    }

    /**
     * 判断使用指定的游戏玩法效果规格是否能正确计算出数值大小(如果依赖的属性不存在等情况可能会失败)
     * 
     * @param InRelevantSpec 用于检查数值计算的游戏玩法效果规格
     * 
     * @return 是否能正确计算出数值大小
     */
    bool CanCalculateMagnitude(const FGameplayEffectSpec& InRelevantSpec) const;

    /**
     * 尝试根据提供的规格计算数值大小。如果规格中缺少必要信息(如捕获的属性),计算可能会失败。
     * 
     * @param InRelevantSpec 用于计算数值大小的游戏玩法效果规格
     * @param OutCalculatedMagnitude [输出] 计算得出的数值大小,计算失败时将被设置为 0.0f
     * 
     * @return 如果计算成功返回 true,否则返回 false
     */
    bool AttemptCalculateMagnitude(const FGameplayEffectSpec& InRelevantSpec, OUT float& OutCalculatedMagnitude, bool WarnIfSetByCallerFail = true, float DefaultSetbyCaller = 0.f) const;

    /** 尝试根据变更的聚合器重新计算数值大小。只有当我们是与给定聚合器关联(非快照)的修饰符时才会重新计算。 */
    bool AttemptRecalculateMagnitudeFromDependentAggregatorChange(const FGameplayEffectSpec& InRelevantSpec, OUT float& OutCalculatedMagnitude, const FAggregator* ChangedAggregator) const;

    /**
     * 收集计算数值大小所需的所有属性捕获定义,并将它们放入提供的数组中
     * 
     * @param OutCaptureDefs [输出] 填充了必要属性捕获定义的数组
     */
    void GetAttributeCaptureDefinitions(OUT TArray<FGameplayEffectAttributeCaptureDefinition>& OutCaptureDefs) const;

    EGameplayEffectMagnitudeCalculation GetMagnitudeCalculationType() const { return 数值计算类型; }

    /** 如果可能,返回数据中输入的数值大小。仅适用于可缩放浮点数或任何无需上下文即可返回数据的类型 */
    bool GetStaticMagnitudeIfPossible(float InLevel, float& OutMagnitude, const FString* ContextString = nullptr) const;

    /** 如果该数值是由调用者设置的,返回与之关联的数据名称 */
    bool GetSetByCallerDataNameIfPossible(FName& OutDataName) const;

    /** 返回由调用者设置的数据结构,用于检查目的 */
    const FSetByCallerFloat& GetSetByCallerFloat() const { return 由调用者设置的数值; }

    /** 如果存在,返回此数值的自定义数值计算类。仅适用于自定义数值 */
    TSubclassOf<UGameplayModMagnitudeCalculation> GetCustomMagnitudeCalculationClass() const;

    /** 实现 Serialize 以清除对不需要的资产的引用 */
    bool Serialize(FArchive& Ar);

    bool operator==(const FGameplayEffectModifierMagnitude& Other) const;
    bool operator!=(const FGameplayEffectModifierMagnitude& Other) const;

#if WITH_EDITOR
    FText GetValueForEditorDisplay() const;
    void ReportErrors(const FString& PathName) const;
#endif

protected:

    /** 用于推导数值大小的计算类型 */
    UPROPERTY(EditDefaultsOnly, Category = Magnitude)
    EGameplayEffectMagnitudeCalculation MagnitudeCalculationType;

    /** 由可缩放浮点数表示的数值大小 */
    UPROPERTY(EditDefaultsOnly, Category = Magnitude)
    FScalableFloat ScalableFloatMagnitude;

    /** 由基于属性的浮点数表示的数值大小
    (系数 * (乘法前累加值 + [根据策略计算得出的属性值])) + 乘法后累加值 */
    UPROPERTY(EditDefaultsOnly, Category = Magnitude)
    FAttributeBasedFloat AttributeBasedMagnitude;

    /** 由自定义计算类表示的数值大小 */
    UPROPERTY(EditDefaultsOnly, Category = Magnitude)
    FCustomCalculationBasedFloat CustomMagnitude;

    /** 由调用者设置的数值大小 */
    UPROPERTY(EditDefaultsOnly, Category = Magnitude)
    FSetByCallerFloatSetByCallerMagnitude;

    friend class UGameplayEffect;
    friend class FGameplayEffectModifierMagnitudeDetails;
};
FGameplayEffectModifierMagnitude

整体功能

FGameplayEffectModifierMagnitude 结构体用于表示游戏玩法效果修饰符的数值大小,它支持多种不同的计算方式,如使用可修改的浮点数、基于属性的计算、自定义计算类或由调用者直接设置等。通过这个结构体,可以灵活地根据不同需求来计算和管理游戏玩法效果的数值。
构造函数
    • 默认构造函数:将 MagnitudeCalculationType 初始化为 EGameplayEffectMagnitudeCalculation::ScalableFloat
    • 其他构造函数:根据传入的不同类型参数(FScalableFloatFAttributeBasedFloatFCustomCalculationBasedFloatFSetByCallerFloat),设置相应的 MagnitudeCalculationType 和具体的数值表示成员。
方法
    • CanCalculateMagnitude:检查使用给定的 FGameplayEffectSpec 是否能正确计算出数值大小,若依赖的属性不存在等情况可能会返回 false
    • AttemptCalculateMagnitude:尝试根据提供的 FGameplayEffectSpec 计算数值大小,若缺少必要信息(如捕获的属性)计算会失败,失败时 OutCalculatedMagnitude 会被设为 0.0f
    • AttemptRecalculateMagnitudeFromDependentAggregatorChange:当关联的聚合器发生变更时,尝试重新计算数值大小,前提是该修饰符与给定聚合器关联且非快照类型。
    • GetAttributeCaptureDefinitions:收集计算数值所需的所有属性捕获定义,并存储到 OutCaptureDefs 数组中。
    • GetMagnitudeCalculationType:返回当前使用的数值计算类型。
    • GetStaticMagnitudeIfPossible:如果可能,返回数据中输入的数值大小,适用于可缩放浮点数等无需上下文的类型。
    • GetSetByCallerDataNameIfPossible:若数值是由调用者设置的,返回与之关联的数据名称。
    • GetSetByCallerFloat:返回由调用者设置的数据结构,用于检查。
    • GetCustomMagnitudeCalculationClass:若存在自定义计算类,返回该类的类型。
    • Serialize:实现序列化功能,清除对不需要的资产的引用。
    • 运算符重载:重载 == 和 != 运算符,用于比较两个 FGameplayEffectModifierMagnitude 结构体是否相等。
    • 编辑器相关方法(#if WITH_EDITOR 部分):GetValueForEditorDisplay 用于在编辑器中显示数值,ReportErrors 用于报告错误。
友元类
  • UGameplayEffect 和 FGameplayEffectModifierMagnitudeDetails 被声明为友元类,这意味着它们可以访问 FGameplayEffectModifierMagnitude 结构体的受保护成员。
 
第九个结构体
template<>
struct TStructOpsTypeTraits<FGameplayEffectModifierMagnitude> : public TStructOpsTypeTraitsBase2<FGameplayEffectModifierMagnitude>
{
    enum
    {
        WithSerializer = true,
    };
};
TStructOpsTypeTraits

模板特化

template<>
struct TStructOpsTypeTraits<FGameplayEffectModifierMagnitude>

这是一个模板特化的语法。template<> 表示这不是一个普通的模板定义,而是针对特定类型 FGameplayEffectModifierMagnitude 的特化版本。也就是说,对于 FGameplayEffectModifierMagnitude 这个结构体

TStructOpsTypeTraits 会有特定的行为,而不是使用通用的模板定义。

 

继承了TStructOpsTypeTraitsBase2
: public TStructOpsTypeTraitsBase2<FGameplayEffectModifierMagnitude>

TStructOpsTypeTraitsBase2 是 Unreal Engine 提供的一个基础模板结构体,它包含了一些默认的结构体操作特性设置。通过继承 TStructOpsTypeTraitsBase2<FGameplayEffectModifierMagnitude>,可以复用其默认的特性设置,同时可以根据需要进行修改和扩展。

枚举设置操作特性

enum
{
    WithSerializer = true,
};
这是一个匿名枚举?????没玩过
,用于定义结构体的操作特性。WithSerializer 是一个布尔类型的标志,当设置为 true 时,表示该结构体支持序列化操作。序列化是将对象的状态转换为可以存储或传输的格式(如二进制数据)的过程,在游戏开发中常用于保存游戏状态、网络传输等场景。当 WithSerializer 为 true 时,Unreal Engine 会调用结构体中定义的 Serialize 方法(如果存在)来完成序列化和反序列化操作。
结合之前的 FGameplayEffectModifierMagnitude 结构体定义,其中有 Serialize 方法:

 

第十个结构体

/** 枚举,代表可用的作用域修饰符聚合器的使用类型 */
UENUM()
enum class EGameplayEffectScopedModifierAggregatorType : uint8
{
    /** 聚合器由属性捕获支持 */
    CapturedAttributeBacked,

    /** 聚合器完全是临时的(充当“临时变量”),必须通过游戏玩法标签来识别 */
    Transient
};
EGameplayEffectScopedModifierAggregatorType

这段代码定义了一个名为 EGameplayEffectScopedModifierAggregatorType 的枚举类,用于表示作用域修饰符聚合器的不同使用类型。在游戏开发中,作用域修饰符聚合器通常用于管理和计算与游戏玩法效果相关的属性值,不同的使用类型决定了聚合器的工作方式和数据来源。

枚举值含义

    • CapturedAttributeBacked:表示聚合器由属性捕获支持。这意味着聚合器的数据来源于对特定属性的捕获,可能是角色的某种属性(如生命值、攻击力等)。在游戏中,可能会根据捕获到的属性值来动态调整某些效果,例如根据角色的攻击力属性来计算技能的伤害值。
    • Transient:表示聚合器是完全临时的,类似于一个 “临时变量”。这种聚合器不依赖于特定的属性捕获,而是需要通过游戏玩法标签来进行识别。在某些场景下,可能需要临时创建一个聚合器来处理一些特定的计算或效果,使用游戏玩法标签可以方便地对这些临时聚合器进行管理和查找。
void ApplyGameplayEffect(const EGameplayEffectScopedModifierAggregatorType aggregatorType)
{
    if (aggregatorType == EGameplayEffectScopedModifierAggregatorType::CapturedAttributeBacked)
    {
        // 处理由属性捕获支持的聚合器
        // 例如,从捕获的属性中获取数据并进行计算
    }
    else if (aggregatorType == EGameplayEffectScopedModifierAggregatorType::Transient)
    {
        // 处理临时聚合器
        // 例如,根据游戏玩法标签查找并使用临时聚合器
    }
}

第十一个结构体

/** 
 * 结构体表示专门用于瞬时发生的“作用域”执行的修饰符信息。这些修饰符仅在计算期间纳入计算,绝不会永久添加到聚合器中。
 */
USTRUCT(BlueprintType)
struct FGameplayEffectExecutionScopedModifierInfo
{
    GENERATED_USTRUCT_BODY()

    // 构造函数
    FGameplayEffectExecutionScopedModifierInfo()
        : AggregatorType(EGameplayEffectScopedModifierAggregatorType::CapturedAttributeBacked)
        , ModifierOp(EGameplayModOp::Additive)
    {}

    FGameplayEffectExecutionScopedModifierInfo(const FGameplayEffectAttributeCaptureDefinition& InCaptureDef)
        : CapturedAttribute(InCaptureDef)
        , AggregatorType(EGameplayEffectScopedModifierAggregatorType::CapturedAttributeBacked)
        , ModifierOp(EGameplayModOp::Additive)
    {
    }

    FGameplayEffectExecutionScopedModifierInfo(const FGameplayTag& InTransientAggregatorIdentifier)
        : TransientAggregatorIdentifier(InTransientAggregatorIdentifier)
        , AggregatorType(EGameplayEffectScopedModifierAggregatorType::Transient)
        , ModifierOp(EGameplayModOp::Additive)
    {
    }

    //作用域修饰符所针对的支持属性
    UPROPERTY(VisibleDefaultsOnly, Category=Execution)
    FGameplayEffectAttributeCaptureDefinition CapturedAttribute;

    //如果作为临时“临时变量”聚合器时,聚合器的标识符
    UPROPERTY(VisibleDefaultsOnly, Category=Execution)
    FGameplayTag TransientAggregatorIdentifier;

    //支持作用域修饰的聚合器类型
    UPROPERTY(VisibleDefaultsOnly, Category=Execution)
    EGameplayEffectScopedModifierAggregatorType AggregatorType;

    //要执行的修饰符操作
    UPROPERTY(EditDefaultsOnly, Category=Execution)
    TEnumAsByte<EGameplayModOp::Type> ModifierOp;

    //作用域修饰符的数值大小
    UPROPERTY(EditDefaultsOnly, Category=Execution)
    FGameplayEffectModifierMagnitude ModifierMagnitude;

    //作用域修饰符的评估通道设置
    UPROPERTY(EditDefaultsOnly, Category=Execution)
    FGameplayModEvaluationChannelSettings EvaluationChannelSettings;

    //修饰符应用所需的源标签要求
    UPROPERTY(EditDefaultsOnly, Category=Execution)
    FGameplayTagRequirements SourceTags;

    //修饰符应用所需的目标标签要求
    UPROPERTY(EditDefaultsOnly, Category=Execution)
    FGameplayTagRequirements TargetTags;
};
FGameplayEffectExecutionScopedModifierInfo(GE执行scope)

构造函数

    • 默认构造函数:将 AggregatorType 初始化为 EGameplayEffectScopedModifierAggregatorType::CapturedAttributeBackedModifierOp 初始化为 EGameplayModOp::Additive
    • 带 FGameplayEffectAttributeCaptureDefinition 参数的构造函数:使用传入的捕获定义初始化 CapturedAttribute,同时设置聚合器类型为 CapturedAttributeBacked,修饰符操作类型为 Additive
    • 带 FGameplayTag 参数的构造函数:使用传入的游戏玩法标签初始化 TransientAggregatorIdentifier,设置聚合器类型为 Transient,修饰符操作类型为 Additive

成员变量

    • CapturedAttribute:作用域修饰符所针对的属性捕获定义,仅在聚合器类型为 CapturedAttributeBacked 时有效,在编辑器中只能查看默认值。
    • TransientAggregatorIdentifier:当聚合器作为临时 “临时变量” 聚合器时,用于标识该聚合器的游戏玩法标签,仅在编辑器中可查看默认值。
    • AggregatorType:支持作用域修饰的聚合器类型,有 CapturedAttributeBacked 和 Transient 两种,仅在编辑器中可查看默认值。
    • ModifierOp:要执行的修饰符操作类型,如加法、乘法等,可在编辑器中编辑默认值。
    • ModifierMagnitude:作用域修饰符的数值大小,可在编辑器中编辑默认值,其计算方式可参考 FGameplayEffectModifierMagnitude 结构体。
    • EvaluationChannelSettings:作用域修饰符的评估通道设置,可在编辑器中编辑默认值,用于控制修饰符的评估过程。
    • SourceTags:修饰符应用所需的源标签要求,可在编辑器中编辑默认值,只有当源对象满足这些标签要求时,修饰符才会应用。
    • TargetTags:修饰符应用所需的目标标签要求,可在编辑器中编辑默认值,只有当目标对象满足这些标签要求时,修饰符才会应用。

使用场景

在游戏中,当需要应用一些临时的属性修改效果时,可以创建 FGameplayEffectExecutionScopedModifierInfo 结构体实例,并根据具体需求设置各个成员变量的值,然后在特定的计算过程中使用这些修饰符信息。例如,当玩家释放一个临时增加攻击力的技能时,可以使用这个结构体来表示该技能带来的临时攻击力提升效果,该效果仅在技能持续期间有效,不会对角色的基础属性产生永久影响。
 
第十一个结构体
USTRUCT(BlueprintType)
struct GAMEPLAYABILITIES_API FConditionalGameplayEffect
{
    GENERATED_USTRUCT_BODY()
    
    // 检查该条件GE是否可以应用
    bool CanApply(const FGameplayTagContainer& SourceTags, float SourceLevel) const;
    //创建一个GESpec句柄
    FGameplayEffectSpecHandle CreateSpec(FGameplayEffectContextHandle EffectContext, float SourceLevel) const;

    /** gameplay effect that will be applied to the target */
    /** 将会应用到目标上的游戏玩法效果类 */
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = GameplayEffect)
    TSubclassOf<UGameplayEffect> EffectClass;

    /** Tags that the source must have for this GE to apply.  If this is blank, then there are no requirements to apply the EffectClass. */
    /** 源对象必须拥有的标签,该GE才会应用。如果为空,则应用该效果类没有任何要求。 */
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = GameplayEffect)
    FGameplayTagContainer RequiredSourceTags;

    bool operator==(const FConditionalGameplayEffect& Other) const;
    bool operator!=(const FConditionalGameplayEffect& Other) const;
};
FConditionalGameplayEffect

整体功能

FGameplayEffectExecutionDefinition 结构体用于定义游戏玩法效果的自定义执行。当游戏玩法效果执行时,它可以调用外部类的特殊逻辑,从而实现更复杂的计算和效果应用。

成员函数

  • GetAttributeCaptureDefinitions
    • 功能:收集并填充执行自定义计算所需的属性捕获定义到 OutCaptureDefs 数组中。每个具体的执行计算负责处理某些捕获定义缺失的情况。
    • 参数:OutCaptureDefs 是一个输出参数,用于存储执行所请求的捕获定义。

成员变量

  • CalculationClass
    • 类型:TSubclassOf<UGameplayEffectExecutionCalculation>
    • 功能:指定游戏玩法效果执行时要运行的自定义执行计算类。开发者可以通过这个类实现特定的计算逻辑。EditDefaultsOnly 表示该属性只能在默认值中编辑。
  • PassedInTags
    • 类型:FGameplayTagContainer
    • 功能:这些标签会直接传入执行逻辑中,可用于在执行过程中进行条件判断,实现不同的执行分支。同样,该属性只能在默认值中编辑。
  • CalculationModifiers
    • 类型:TArray<FGameplayEffectExecutionScopedModifierInfo>
    • 功能:存储在执行计算期间 “就地” 应用的修饰符。这些修饰符会在执行过程中对属性值进行临时修改。该数组中的元素类型是 FGameplayEffectExecutionScopedModifierInfo,可参考之前对该结构体的解释。
  • ConditionalGameplayEffects
    • 类型:TArray<FConditionalGameplayEffect>
    • 功能:如果执行成功,这些条件游戏玩法效果将应用于执行的目标。如果没有选择执行类,这些效果将始终应用。每个元素的类型是 FConditionalGameplayEffect,表示有条件应用的游戏玩法效果。

使用场景

在游戏开发中,这种自定义执行的设计非常有用。例如,在实现一个复杂的技能效果时,技能的伤害计算可能不仅仅依赖于角色的基础属性,还需要考虑目标的状态、环境因素等。通过 FGameplayEffectExecutionDefinition 结构体,可以定义一个自定义的执行计算类,在其中实现复杂的伤害计算逻辑,并根据不同的条件应用额外的效果。
 
第十二个结构体

FGameplayModifierInfo 结构体用于描述游戏玩法中的修饰符信息,它主要说明了要修改的目标(属性),但不涉及具体的修改逻辑实现。

在游戏开发中,这样的结构体可用于定义各种属性修改规则,比如角色属性的增益、减益效果等。

    /**
     * 此修饰符的数值运算类型:覆盖、加法、乘法等
     * 当多个修饰符聚合在一起时,计算公式为:
     * ((基础值 + 基础加法值) * 加法乘法因子 / 加法除法因子 * 复合乘法因子) + 最终加法值
     */
    UPROPERTY(EditDefaultsOnly, Category=GameplayModifier)
    TEnumAsByte<EGameplayModOp::Type> ModifierOp = EGameplayModOp::Additive;

    /** 修饰符的数值大小 */
    UPROPERTY(EditDefaultsOnly, Category=GameplayModifier)
    FGameplayEffectModifierMagnitude ModifierMagnitude;

    /** 修饰符的评估通道设置 */
    UPROPERTY(EditDefaultsOnly, Category=GameplayModifier)
    FGameplayModEvaluationChannelSettings EvaluationChannelSettings;

    UPROPERTY(EditDefaultsOnly, Category=GameplayModifier)
    FGameplayTagRequirements    SourceTags;

    UPROPERTY(EditDefaultsOnly, Category=GameplayModifier)
    FGameplayTagRequirements    TargetTags;

    /** 相等/不相等运算符 */
    bool operator==(const FGameplayModifierInfo& Other) const;
    bool operator!=(const FGameplayModifierInfo& Other) const;
};
FGameplayModifierInfo

成员变量

    1. Attribute
      • 类型:FGameplayAttribute
      • 功能:表示要修改的属性。这个属性可以是角色的生命值、攻击力等各种游戏中的属性。meta=(FilterMetaTag = "HideFromModifiers") 是元数据设置,可能用于在某些过滤操作中隐藏该属性。
    2. ModifierOp
      • 类型:TEnumAsByte<EGameplayModOp::Type>
      • 功能:指定修饰符的数值运算类型,如覆盖、加法、乘法等。默认值为 EGameplayModOp::Additive,即加法运算。当多个修饰符对同一个属性进行修改时,会按照特定的公式 ((BaseValue + AddBase) * MultiplyAdditive / DivideAdditive * MultiplyCompound) + AddFinal 进行聚合计算。
    3. ModifierMagnitude
      • 类型:FGameplayEffectModifierMagnitude
      • 功能:表示修饰符的数值大小,其计算方式可以是可缩放浮点数、基于属性的计算、自定义计算类或由调用者直接设置等,具体可参考 FGameplayEffectModifierMagnitude 结构体的定义。
    4. EvaluationChannelSettings
      • 类型:FGameplayModEvaluationChannelSettings
      • 功能:用于设置修饰符的评估通道,可能与修饰符的生效条件、评估顺序等相关。
    5. SourceTags
      • 类型:FGameplayTagRequirements
      • 功能:表示源对象需要满足的标签要求。只有当源对象具备这些标签时,该修饰符才可能生效。
    6. TargetTags
      • 类型:FGameplayTagRequirements
      • 功能:表示目标对象需要满足的标签要求。只有当目标对象具备这些标签时,该修饰符才可能生效。

使用场景

在游戏中,当需要对角色的属性进行修改时,可以创建 FGameplayModifierInfo 结构体实例,并设置相应的属性和修饰符信息。
例如,当角色获得一个攻击力提升的技能时,可以创建一个 FGameplayModifierInfo 实例,将 Attribute 设置为攻击力属性,ModifierOp 设置为加法,ModifierMagnitude 设置为提升的数值,然后应用这个修饰符到角色的攻击力属性上。
 
 第十三个结构体
/**
 * FGameplayEffectCue
 *  这是一种可以与 UGameplayEffect 关联的视觉或听觉提示。
 *  本质上,它是一个游戏玩法标签加上一个最小/最大等级范围,用于将游戏玩法效果的等级映射到游戏玩法提示系统使用的归一化值。
 */

USTRUCT(BlueprintType)
struct FGameplayEffectCue
{
    GENERATED_USTRUCT_BODY()
    // 默认构造函数
    FGameplayEffectCue()
        : MinLevel(0.f)
        , MaxLevel(0.f)
    {
    }
    // 带参数的构造函数
    FGameplayEffectCue(const FGameplayTag& InTag, float InMinLevel, float InMaxLevel)
        : MinLevel(InMinLevel)
        , MaxLevel(InMaxLevel)
    {
        GameplayCueTags.AddTag(InTag);
    }


    // 用作提示强度来源的属性。如果未指定,则使用等级
    UPROPERTY(EditDefaultsOnly, Category = GameplayCue)
    FGameplayAttribute MagnitudeAttribute;

    // 此提示支持的最小等级
    UPROPERTY(EditDefaultsOnly, Category = GameplayCue)
    float    MinLevel;

    //此提示支持的最大等级
    UPROPERTY(EditDefaultsOnly, Category = GameplayCue)
    float    MaxLevel;

    // 当此提示激活时传递给游戏玩法提示处理器的标签
    UPROPERTY(EditDefaultsOnly, Category = GameplayCue, meta = (Categories="GameplayCue"))
    FGameplayTagContainer GameplayCueTags;

    float NormalizeLevel(float InLevel)
    {
        float Range = MaxLevel - MinLevel;
        if (Range <= KINDA_SMALL_NUMBER)
        {
            return 1.f;
        }

        return FMath::Clamp((InLevel - MinLevel) / Range, 0.f, 1.0f);
    }
};
FGameplayEffectCue

FGameplayEffectCue 结构体用于定义与游戏玩法效果相关的视觉或听觉提示。

它通过游戏玩法标签和等级范围,将游戏玩法效果的等级映射为一个归一化值,这个归一化值可以被游戏玩法提示系统使用,以实现不同等级下的不同提示效果。

成员变量

  1. MagnitudeAttribute
    • 类型:FGameplayAttribute
    • 功能:指定用作提示强度来源的属性。如果没有指定这个属性,那么将使用游戏玩法效果的等级来确定提示的强度。
  2. MinLevel
    • 类型:float
    • 功能:表示此提示支持的最小等级。低于这个等级时,可能不会触发该提示或者按照最小等级的效果处理。
  3. MaxLevel
    • 类型:float
    • 功能:表示此提示支持的最大等级。高于这个等级时,可能按照最大等级的效果处理。
  4. GameplayCueTags
    • 类型:FGameplayTagContainer
    • 功能:存储当此提示激活时要传递给游戏玩法提示处理器的标签。这些标签可以用于区分不同类型的提示或者控制提示的具体行为。

构造函数

  1. 默认构造函数
    • 将 MinLevel 和 MaxLevel 初始化为 0.0f
  2. 带参数的构造函数
    • 接受一个 FGameplayTag 类型的标签和最小、最大等级作为参数。将输入的标签添加到 GameplayCueTags 中,并设置最小和最大等级。

成员函数

  • NormalizeLevel
    • 功能:将输入的等级 InLevel 归一化到 [0, 1] 的范围。首先计算最大等级和最小等级的差值 Range,如果这个差值小于一个很小的数(KINDA_SMALL_NUMBER),则直接返回 1.0f。否则,使用公式 (InLevel - MinLevel) / Range 计算归一化值,并使用 FMath::Clamp 函数将结果限制在 [0, 1] 范围内。

使用场景

在游戏中,当某个游戏玩法效果触发时,可以根据其等级和 FGameplayEffectCue 结构体的设置,计算出归一化的等级值,然后根据这个值和 GameplayCueTags 来播放不同强度的视觉或听觉提示,例如不同等级的技能释放特效、音效等。
 
第十四个结构体
//用于以安全方式合并来自父蓝图和子蓝图标签的结构体
USTRUCT(BlueprintType)
struct GAMEPLAYABILITIES_API FInheritedTagContainer
{
    GENERATED_USTRUCT_BODY()

    //我继承的标签、我添加的标签减去我移除的标签
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Application, meta=(Tooltip="CombinedTags = Inherited - Removed + Added"))
    FGameplayTagContainer CombinedTags;

    //我拥有的标签(除了我父级的标签之外)
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Application, meta=(DisplayName="Add to Inherited"))
    FGameplayTagContainer Added;

    //应该移除的标签(仅当我的父级拥有这些标签时)。注意:我们不能用它来移除目标上存在的标签。它仅修改合并标签的结果。
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Application, meta=(DisplayName="Remove from Inherited"))
    FGameplayTagContainer Removed;

    // 根据父级的继承标签容器更新自身的继承标签属性
    void UpdateInheritedTagProperties(const FInheritedTagContainer* Parent);

    //将添加和移除的标签应用到传入的容器(不一定要是之前配置的父级容器!)
    void ApplyTo(FGameplayTagContainer& ApplyToContainer) const;

    //添加一个除任何继承标签之外还会出现的标签
    void AddTag(const FGameplayTag& TagToAdd);

    //移除一个会从任何继承标签中省略的标签
    void RemoveTag(const FGameplayTag& TagToRemove);

    bool operator==(const FInheritedTagContainer& Other) const;
    bool operator!=(const FInheritedTagContainer& Other) const;
};
FInheritedTagContainer

FInheritedTagContainer 结构体的主要目的是安全地合并来自父蓝图和子蓝图的游戏玩法标签。它通过管理添加和移除的标签,计算出最终的合并标签集合,使得在蓝图继承体系中能够灵活地处理标签的继承和修改。

成员变量

  1. CombinedTags
    • 类型:FGameplayTagContainer
    • 功能:存储合并后的标签集合,其计算方式为继承的标签减去移除的标签再加上添加的标签(CombinedTags = Inherited - Removed + Added)。VisibleAnywhere 表示该属性在任何地方都可见,BlueprintReadOnly 表示在蓝图中只读。
  2. Added
    • 类型:FGameplayTagContainer
    • 功能:存储除父级标签之外,当前蓝图额外添加的标签。EditDefaultsOnly 表示该属性只能在默认值中编辑,BlueprintReadOnly 表示在蓝图中只读。
  3. Removed
    • 类型:FGameplayTagContainer
    • 功能:存储要从继承的标签中移除的标签集合,但仅当父级拥有这些标签时才会移除。需要注意的是,它不会移除目标上已存在的标签,仅影响合并标签的结果。同样,该属性只能在默认值中编辑,在蓝图中只读。

成员函数

  1. UpdateInheritedTagProperties
    • 功能:根据传入的父级 FInheritedTagContainer 指针,更新自身的继承标签属性,重新计算 CombinedTags
    • 参数:Parent 为父级的 FInheritedTagContainer 指针。
  2. ApplyTo
    • 功能:将当前结构体中添加和移除的标签应用到传入的 FGameplayTagContainer 容器中,对该容器中的标签进行相应的添加和移除操作。
    • 参数:ApplyToContainer 是要应用标签操作的容器。
  3. AddTag
    • 功能:向 Added 标签容器中添加一个标签,该标签会出现在最终的合并标签集合中。
    • 参数:TagToAdd 是要添加的标签。
  4. RemoveTag
    • 功能:向 Removed 标签容器中添加一个标签,该标签会从继承的标签中省略。
    • 参数:TagToRemove 是要移除的标签。

使用场景

在游戏开发中,当涉及到蓝图的继承体系,并且需要对标签进行管理时,FInheritedTagContainer 结构体就非常有用。
例如,在角色蓝图的继承中,父角色蓝图有一些通用的标签,子角色蓝图可以通过 Added 和 Removed 标签容器来添加或移除特定的标签,最终通过 CombinedTags 得到合并后的标签集合,用于游戏中的各种逻辑判断,如技能释放条件、状态判断等。
 
/**************************************************************************************这一部分往下是处理持续时间的*****************************************************************************************/
第十五个是枚举类型
/** 游戏玩法效果的持续时间策略 */
UENUM()
enum class EGameplayEffectDurationType : uint8
{
    /** 此效果立即应用(无持续时间) */
    Instant,
    /** 此效果永久持续 */
    Infinite,
    /** 此效果的持续时间将由一个数值指定 */
    HasDuration
};

EGameplayEffectDurationType 是一个枚举类,用于定义游戏玩法效果的持续时间策略。在游戏开发中,不同的技能、状态等游戏玩法效果可能有不同的持续时间表现,通过这个枚举可以方便地对这些效果的持续时间类型进行分类和管理。

 
 第十六个也是枚举类型
/** 枚举,用于定义游戏玩法效果在堆叠时处理周期的策略 */
UENUM()
enum class EGameplayEffectStackingPeriodPolicy : uint8
{
    /** 每当成功应用一次堆叠时,周期性效果到达下一次触发的进度将被丢弃 */
    ResetOnSuccessfulApplication,

    /** 无论堆叠是否应用,周期性效果到达下一次触发的进度都不会被重置 */
    NeverReset,
};

此代码定义了一个名为 EGameplayEffectStackingPeriodPolicy 的枚举类,该枚举用于描述游戏玩法效果在堆叠时处理周期的不同策略。在游戏开发里,某些游戏玩法效果可以堆叠,比如多次施加同一个增益效果;同时部分效果具有周期性,例如每隔一段时间产生一次伤害或者恢复一定数值。该枚举规定了在效果堆叠时,周期性效果的进度该如何处理。

  • enum class:C++11 引入的强类型枚举,它能避免枚举值泄漏到周围的命名空间,并且增强了类型安全性。
  • EGameplayEffectStackingPeriodPolicy:枚举类的名称,用于表示游戏玩法效果堆叠时的周期处理策略。
  • : uint8:指定枚举底层使用 uint8 类型来存储枚举值,这样做可以节省内存。
 
第十七个也是枚举类型
/** 枚举类型,用于定义游戏玩法效果在堆叠时处理周期的策略 */
UENUM() // 虚幻引擎中用于标记枚举的宏,使其支持反射和序列化等功能
enum class EGameplayEffectStackingPeriodPolicy : uint8 // 定义一个名为 EGameplayEffectStackingPeriodPolicy 的枚举类,底层类型为 uint8
{
    /** 每当成功进行一次堆叠应用时,周期性效果到下一次触发的进度将被舍弃 */
    ResetOnSuccessfulApplication, // 成功堆叠时重置进度的策略

    /** 无论是否进行堆叠应用,周期性效果到下一次触发的进度都不会被重置 */
    NeverReset, // 无论堆叠与否都不重置进度的策略
};
这段代码定义了一个枚举类 EGameplayEffectStackingPeriodPolicy,用于表示在游戏中处理周期性游戏玩法效果堆叠时的不同策略。在游戏里,有些技能或效果可能会有周期性触发的机制(例如每秒恢复一定生命值),并且这些效果可能会堆叠(多次施加相同效果)。这个枚举类提供了两种处理堆叠时周期进度的策略:
    • ResetOnSuccessfulApplication:每次成功堆叠时,周期性效果到下一次触发的进度会被重置为零。
    • NeverReset:无论是否进行堆叠操作,周期性效果到下一次触发的进度都不会改变。
第十八个也是枚举类型
/** 枚举类型,用于定义处理过期的游戏玩法效果堆叠(基于持续时间的效果)的策略 */
UENUM() // Unreal Engine 中用于标记枚举的宏,使枚举可用于反射和序列化等操作
enum class EGameplayEffectStackingExpirationPolicy : uint8 // 定义一个名为 EGameplayEffectStackingExpirationPolicy 的枚举类,底层类型为 uint8
{
    /** 当活动的游戏玩法效果过期时,整个堆叠将被清除 */
    ClearEntireStack,

    /** 当前堆叠计数将减 1,并且持续时间将被刷新。游戏玩法效果不会 “重新应用”,只是以少一个堆叠的状态继续存在 */
    RemoveSingleStackAndRefreshDuration,

    /** 游戏玩法效果的持续时间将被刷新。这实际上使效果的持续时间变为无限。这可用于通过 OnStackCountChange 回调手动处理堆叠计数的减少 */
    RefreshDuration,
};

此枚举类 EGameplayEffectStackingExpirationPolicy 用于定义在处理基于持续时间的游戏玩法效果堆叠过期时的不同策略。在游戏中,某些效果可以堆叠,并且有一定的持续时间,当这些效果过期时,需要根据不同的策略来处理堆叠。

枚举值解释

  1. ClearEntireStack
    • 含义:当游戏玩法效果过期时,会将整个效果堆叠清除。例如,一个增加攻击力的效果可以堆叠 5 次,当这个效果过期时,所有 5 次堆叠都会被移除,角色的攻击力加成会完全消失。
    • 使用场景:适用于需要一次性移除所有堆叠效果的情况,比如一些限时的群体增益效果,过期后需要全部清除。
  2. RemoveSingleStackAndRefreshDuration
    • 含义:效果过期时,会将堆叠计数减 1,同时刷新效果的持续时间。效果不会重新应用,只是以少一个堆叠的状态继续存在。例如,攻击力加成效果原本堆叠了 3 次,过期时会变为 2 次堆叠,并且持续时间重新开始计算。
    • 使用场景:适用于希望逐步减少堆叠数量,但又希望效果持续存在的情况,比如一些可以逐步衰减的状态效果。
  3. RefreshDuration
    • 含义:效果过期时,仅刷新其持续时间,这会使效果的持续时间在某种程度上变为无限。可以通过 OnStackCountChange 回调手动处理堆叠计数的减少。例如,一个防御力提升效果,每次过期时都刷新持续时间,开发者可以在合适的时候通过回调来减少堆叠数量。
    • 使用场景:适用于需要让效果持续存在,但又需要手动控制堆叠数量的情况,比如一些特殊的技能效果,需要根据特定条件来调整堆叠。
第十九个也是枚举类型
/** 枚举类型,用于定义在游戏玩法效果的抑制状态解除时,处理其周期的策略 */
UENUM() // Unreal Engine 中用于标记枚举的宏,支持反射和序列化等功能
enum class EGameplayEffectPeriodInhibitionRemovedPolicy : uint8 // 定义名为 EGameplayEffectPeriodInhibitionRemovedPolicy 的枚举类,底层类型为 uint8
{
    /** 不重置。周期计时将继续,就好像抑制状态从未发生过一样。 */
    NeverReset,

    /** 重置周期。从抑制状态解除开始,下一次执行将在一个完整周期后发生。 */
    ResetPeriod,

    /** 立即执行,并重置周期。 */
    ExecuteAndResetPeriod,
};

这段代码定义了一个枚举类 EGameplayEffectPeriodInhibitionRemovedPolicy,用于确定当游戏玩法效果的抑制状态被移除时,如何处理该效果的周期。在游戏里,某些游戏玩法效果可能会有周期性的触发机制(如每秒恢复一定生命值),但这些效果可能会因为某些原因(例如角色被眩晕)进入抑制状态,当抑制状态解除后,就需要根据不同的策略来处理效果的周期。

枚举值解释

  1. NeverReset
    • 含义:当抑制状态解除时,效果的周期计时不会被重置,就好像抑制状态从未发生过一样。例如,一个每 5 秒触发一次的周期性伤害效果,在第 3 秒时进入抑制状态,抑制状态持续了 2 秒,当抑制状态解除后,该效果会在第 5 秒(从最初开始计时)触发下一次伤害,周期计时不受抑制状态的影响。
    • 使用场景:适用于那些希望周期不受抑制状态干扰,保持连续计时的游戏玩法效果。比如一些持续性的环境效果,即使角色暂时受到抑制,环境效果的周期也不应改变。
  2. ResetPeriod
    • 含义:当抑制状态解除时,效果的周期会被重置。从抑制状态解除的时刻开始计算,下一次效果执行将在一个完整的周期后发生。继续上面的例子,在第 3 秒进入抑制状态,持续 2 秒,抑制状态解除后,下一次伤害将在 5 秒后触发,相当于重新开始一个新的周期。
    • 使用场景:适用于需要在抑制状态解除后重新开始周期的游戏玩法效果。例如,某些技能的周期性增益效果,在角色被控制期间暂停,控制解除后重新开始计时。
  3. ExecuteAndResetPeriod
    • 含义:当抑制状态解除时,效果会立即执行一次,然后周期被重置。还是以每 5 秒触发一次的周期性伤害效果为例,在第 3 秒进入抑制状态,持续 2 秒,抑制状态解除时会立即触发一次伤害,然后下一次伤害将在 5 秒后再次触发。
    • 使用场景:适用于需要在抑制状态解除时立即产生一次效果,并重新开始周期的情况。比如一些具有惩罚机制的周期性效果,当角色的抑制状态解除时,先立即施加一次惩罚效果,然后重新开始周期。
 
 
 
 
 
 
 
 
 
 
 

 

posted @ 2025-02-18 23:25  mcwhirr  阅读(89)  评论(0)    收藏  举报