跳转至

Building Cost Types

本页说明建筑成本系统使用的公共数据类型,包括成本目标、成本条目、运行时上下文、执行结果和 UI 数据。

类型关系

FBuildingCostEntry
└── Costs
    └── FBuildingCostTargetAmount
        └── TargetData
            └── FBuildingCostTargetBase 派生类型

UBuildingCostEvaluator
├── CanAfford
├── Consume
└── EvaluateForUI

UBuildingCostSet
└── CostEntries
    └── FBuildingCostEntry

成本目标类型

成本目标用于标识 Evaluator 需要检查或消耗的资源、货币或物品。

所有成本目标均继承自:

FBuildingCostTargetBase

FBuildingCostTargetBase

成本目标的基础结构,本身不包含数据。

USTRUCT(BlueprintType)
struct FBuildingCostTargetBase
{
    GENERATED_BODY()
};

项目可以继承该结构,创建自定义成本目标类型。

内置目标类型

类型 字段 数据类型 说明
FBuildingCostTarget_Name Name FName 使用名称标识目标。
FBuildingCostTarget_IntId Id int32 使用整数 ID 标识目标。
FBuildingCostTarget_GameplayTag Tag FGameplayTag 使用 Gameplay Tag 标识目标。
FBuildingCostTarget_PrimaryAssetId AssetId FPrimaryAssetId 使用 Primary Asset ID 标识目标。
FBuildingCostTarget_SoftObject Asset TSoftObjectPtr<UObject> 使用软对象引用标识目标。

FBuildingCostTarget_Name

USTRUCT(BlueprintType)
struct FBuildingCostTarget_Name
    : public FBuildingCostTargetBase
{
    GENERATED_BODY()

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost"
    )
    FName Name = NAME_None;
};

适合使用资源名称或项目自定义名称作为标识。

FBuildingCostTarget_IntId

USTRUCT(BlueprintType)
struct FBuildingCostTarget_IntId
    : public FBuildingCostTargetBase
{
    GENERATED_BODY()

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost"
    )
    int32 Id = INDEX_NONE;
};

适合使用数据库 ID、物品 ID 或资源编号的项目。

FBuildingCostTarget_GameplayTag

USTRUCT(BlueprintType)
struct FBuildingCostTarget_GameplayTag
    : public FBuildingCostTargetBase
{
    GENERATED_BODY()

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost"
    )
    FGameplayTag Tag;
};

例如:

Resource.Wood
Resource.Stone
Currency.Gold

FBuildingCostTarget_PrimaryAssetId

USTRUCT(BlueprintType)
struct FBuildingCostTarget_PrimaryAssetId
    : public FBuildingCostTargetBase
{
    GENERATED_BODY()

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost"
    )
    FPrimaryAssetId AssetId;
};

适合使用 Unreal Engine Primary Asset 系统管理物品或资源。

FBuildingCostTarget_SoftObject

USTRUCT(BlueprintType)
struct FBuildingCostTarget_SoftObject
    : public FBuildingCostTargetBase
{
    GENERATED_BODY()

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost"
    )
    TSoftObjectPtr<UObject> Asset;
};

软引用不保证目标资产已经加载,Evaluator 应根据项目需求处理加载。

FBuildingCostTargetAmount

FBuildingCostTargetAmount 表示一项成本目标和对应数量。

USTRUCT(BlueprintType)
struct FBuildingCostTargetAmount
{
    GENERATED_BODY()

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost"
    )
    bool bEnabled = true;

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost"
    )
    TInstancedStruct<FBuildingCostTargetBase> TargetData;

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost",
        meta = (ClampMin = "0")
    )
    int32 Amount = 1;

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost|UI"
    )
    FText DisplayName;

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost|UI"
    )
    TObjectPtr<UTexture2D> Icon = nullptr;
};
字段 数据类型 默认值 说明
bEnabled bool true 是否启用当前成本目标。
TargetData TInstancedStruct<FBuildingCostTargetBase> 当前目标的具体数据。
Amount int32 1 需要检查或消耗的数量。
DisplayName FText 可选的 UI 名称覆盖。
Icon UTexture2D* nullptr 可选的 UI 图标覆盖。

TargetData 只能选择继承自 FBuildingCostTargetBase 的结构。

例如:

Target Data 类型 示例
FBuildingCostTarget_GameplayTag Resource.Wood
FBuildingCostTarget_IntId 1001
FBuildingCostTarget_Name Wood
FBuildingCostTarget_PrimaryAssetId Item:DA_Wood
FBuildingCostTarget_SoftObject 物品数据资产

DisplayNameIcon 只用于 UI 覆盖。未配置时,Evaluator 可以从目标数据或项目资源系统中获取显示信息。

FBuildingCostEntry

FBuildingCostEntry 表示由同一个 Evaluator 处理的一组成本目标。

USTRUCT(BlueprintType)
struct FBuildingCostEntry
{
    GENERATED_BODY()

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost"
    )
    bool bEnabled = true;

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost"
    )
    FGameplayTag CostTypeTag;

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost"
    )
    TSubclassOf<UBuildingCostEvaluator> EvaluatorClass;

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost"
    )
    TArray<FBuildingCostTargetAmount> Costs;
};
字段 数据类型 默认值 说明
bEnabled bool true 是否启用当前成本条目。
CostTypeTag FGameplayTag 当前条目的成本类型。
EvaluatorClass TSubclassOf<UBuildingCostEvaluator> 可选的 Evaluator 覆盖。
Costs TArray<FBuildingCostTargetAmount> 当前 Evaluator 处理的目标列表。

CostTypeTag

CostTypeTag 用于标识成本类型,例如:

Cost.Resource
Cost.Currency
Cost.Item
Cost.Reputation
Cost.BuildingPoint

EvaluatorClass 未配置时,系统会根据 CostTypeTag 从项目设置中的 Default Evaluators 查找 Evaluator。

默认 Evaluator 使用 Gameplay Tag 精确匹配,不会自动匹配父标签或子标签。

EvaluatorClass

配置状态 使用的 Evaluator
已配置 使用当前 Entry 指定的 EvaluatorClass
未配置 根据 CostTypeTag 查找项目默认 Evaluator。

Costs

一个 Entry 可以包含多个由同一 Evaluator 处理的目标。

例如:

目标 数量
Resource.Wood 10
Resource.Stone 5

FBuildingCostContext

FBuildingCostContext 提供成本检查和资源消耗所需的运行时上下文。

Evaluator 应从 Context 中获取需要的对象,不建议长期保存这些引用。

USTRUCT(BlueprintType)
struct FBuildingCostContext
{
    GENERATED_BODY()

    UPROPERTY(BlueprintReadOnly, Category = "Building|Cost")
    TObjectPtr<UObject> WorldContextObject = nullptr;

    UPROPERTY(BlueprintReadOnly, Category = "Building|Cost")
    TObjectPtr<AController> Controller = nullptr;

    UPROPERTY(BlueprintReadOnly, Category = "Building|Cost")
    TObjectPtr<UBuildingBuildComponent>
        BuildingBuildComponent = nullptr;

    UPROPERTY(BlueprintReadOnly, Category = "Building|Cost")
    TObjectPtr<const UBuildingDataAsset>
        BuildingData = nullptr;

    UPROPERTY(BlueprintReadOnly, Category = "Building|Cost")
    FTransform BuildTransform = FTransform::Identity;
};
字段 数据类型 默认值 说明
WorldContextObject UObject* nullptr 用于获取当前 UWorld
Controller AController* nullptr 当前建筑操作的 Controller。
BuildingBuildComponent UBuildingBuildComponent* nullptr 发起当前建筑操作的组件。
BuildingData const UBuildingDataAsset* nullptr 当前建筑数据资产。
BuildTransform FTransform Identity 当前请求的建筑世界变换。

WorldContextObject

用于解析当前世界:

UWorld* World =
    IsValid(Context.WorldContextObject)
    ? Context.WorldContextObject->GetWorld()
    : nullptr;

Controller

表示当前建筑操作的发起者。

Evaluator 可以通过它获取:

  • Pawn
  • Player State
  • Inventory Component
  • Currency Component
  • 项目权限数据

该字段类型为 AController*,也可以接收 AI Controller。

BuildingBuildComponent

表示发起当前操作的建筑组件。

项目可以通过它获取:

  • 组件 Owner
  • Pawn
  • 背包或资源组件
  • 阵营或聚落数据
  • 项目自定义成本来源

BuildingData

表示当前正在评估的建筑配置。

Evaluator 可以读取建筑类型、Gameplay Tags、Cost Set 和项目自定义配置。

该对象为只读,不应在成本检查过程中修改。

BuildTransform

表示当前建筑请求的世界变换。

可以用于实现与位置有关的成本或要求,例如:

  • 根据区域计算成本
  • 根据建筑高度增加费用
  • 检查领地或位置权限
  • 根据距离计算消耗

普通资源成本可以忽略该字段。

有效性检查

Evaluator 不应假设 Context 中的所有对象始终有效。

if (!IsValid(Context.Controller))
{
    return FBuildingCostResult::Failure(
        NSLOCTEXT(
            "BuildingCost",
            "InvalidController",
            "Unable to resolve the building owner."
        )
    );
}

具体需要检查哪些字段,由 Evaluator 的实现决定。

FBuildingCostResult

FBuildingCostResult 表示成本检查或消耗结果。

USTRUCT(BlueprintType)
struct FBuildingCostResult
{
    GENERATED_BODY()

    UPROPERTY(BlueprintReadOnly, Category = "Building|Cost")
    bool bSuccess = true;

    UPROPERTY(BlueprintReadOnly, Category = "Building|Cost")
    FText FailReason;
};
字段 数据类型 默认值 说明
bSuccess bool true 操作是否成功。
FailReason FText 操作失败时的原因。

Success

创建成功结果。

static FBuildingCostResult Success();

Failure

创建失败结果。

static FBuildingCostResult Failure(
    const FText& Reason
);
类型 名称 数据类型 说明
Param Reason const FText& 失败原因。
Return Result FBuildingCostResult 失败结果。

这些辅助函数主要供 C++ 使用。

FBuildingCostLine

FBuildingCostLine 表示建造 UI 中的一行资源、货币或物品成本。

USTRUCT(BlueprintType)
struct FBuildingCostLine
{
    GENERATED_BODY()

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    FText DisplayName;

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    TObjectPtr<UTexture2D> Icon = nullptr;

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    int32 RequiredAmount = 0;

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    int32 OwnedAmount = 0;

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    bool bEnough = true;

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    FGameplayTag CostTypeTag;
};
字段 数据类型 默认值 说明
DisplayName FText 成本名称。
Icon UTexture2D* nullptr 成本图标。
RequiredAmount int32 0 所需数量。
OwnedAmount int32 0 当前拥有数量。
bEnough bool true 当前数量是否足够。
CostTypeTag FGameplayTag 当前成本类型。

FBuildingRequirementLine

FBuildingRequirementLine 表示一项非资源类建造要求。

常见用途包括:

  • 玩家等级
  • 科技解锁
  • 建筑权限
  • 声望要求
  • 项目自定义限制
USTRUCT(BlueprintType)
struct FBuildingRequirementLine
{
    GENERATED_BODY()

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    FText DisplayName;

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    FText CurrentValueText;

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    FText RequiredValueText;

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    bool bPassed = true;

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    FText FailReason;
};
字段 数据类型 默认值 说明
DisplayName FText 要求名称。
CurrentValueText FText 当前状态或数值。
RequiredValueText FText 需要满足的状态或数值。
bPassed bool true 当前要求是否通过。
FailReason FText 未通过时的原因。

FBuildingBuildCheckResult

FBuildingBuildCheckResult 是所有成本和要求的 UI 聚合结果。

USTRUCT(BlueprintType)
struct FBuildingBuildCheckResult
{
    GENERATED_BODY()

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    bool bCanBuild = true;

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    TArray<FBuildingCostLine> CostLines;

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    TArray<FBuildingRequirementLine> RequirementLines;

    UPROPERTY(BlueprintReadWrite, Category = "Building|UI")
    FText FirstFailReason;
};
字段 数据类型 默认值 说明
bCanBuild bool true 所有成本和要求是否通过。
CostLines TArray<FBuildingCostLine> 成本 UI 数据。
RequirementLines TArray<FBuildingRequirementLine> 非资源要求 UI 数据。
FirstFailReason FText 第一个失败原因。

该结果可以由以下接口生成:

UBuildingCostEvaluator::EvaluateForUI

或:

UBuildingBuildComponent::EvaluateBuildForUI

UBuildingCostEvaluator

UBuildingCostEvaluator 是成本处理器的基础类。

项目可以通过蓝图或 C++ 继承该类,对接自己的背包、货币或资源系统。

接口 说明
CanAfford 检查当前成本是否能够支付。
Consume 消耗当前成本。
EvaluateForUI 生成 UI 使用的成本和要求信息。

CanAfford

UFUNCTION(
    BlueprintNativeEvent,
    BlueprintCallable,
    Category = "Building|Cost"
)
FBuildingCostResult CanAfford(
    const FBuildingCostContext& Context,
    const FBuildingCostEntry& Entry
) const;

该接口只执行检查,不应修改资源状态。

Consume

UFUNCTION(
    BlueprintNativeEvent,
    BlueprintCallable,
    Category = "Building|Cost"
)
FBuildingCostResult Consume(
    const FBuildingCostContext& Context,
    const FBuildingCostEntry& Entry
) const;

该接口负责实际消耗资源。

实现时应在修改资源前再次检查可用数量,因为运行时数据可能已经发生变化。

EvaluateForUI

UFUNCTION(
    BlueprintNativeEvent,
    BlueprintCallable,
    Category = "Building|Cost"
)
FBuildingBuildCheckResult EvaluateForUI(
    const FBuildingCostContext& Context,
    const FBuildingCostEntry& Entry
) const;

该接口用于生成 UI 数据,不应消耗或修改资源。

UBuildingCostSet

UBuildingCostSet 是建筑使用的成本配置资产。

UCLASS(BlueprintType)
class UBuildingCostSet : public UDataAsset
{
    GENERATED_BODY()

public:

    UPROPERTY(
        EditAnywhere,
        BlueprintReadOnly,
        Category = "Building|Cost"
    )
    TArray<FBuildingCostEntry> CostEntries;
};

CostEntries

CostEntries 保存建筑需要检查和消耗的成本条目。

一个 Cost Set 可以同时包含多种成本:

Cost.Resource
Cost.Currency
Cost.Item

CanAfford

FBuildingCostResult CanAfford(
    const FBuildingCostContext& Context
) const;

检查所有启用的成本条目,但不消耗资源。

Consume

FBuildingCostResult Consume(
    const FBuildingCostContext& Context
) const;

调用各个成本条目的 Evaluator 执行资源消耗。

EvaluateForUI

void EvaluateForUI(
    const FBuildingCostContext& Context,
    FBuildingBuildCheckResult& InOutResult
) const;

将各个成本条目的 UI 数据写入现有的检查结果。

UI 使用建议

数据 用途
bCanBuild 控制确认按钮是否可用。
CostLines 显示资源、货币或物品成本。
RequirementLines 显示等级、权限等要求。
FirstFailReason 显示简短失败提示。
bEnough 标记单项成本是否满足。
bPassed 标记单项要求是否通过。

类型用途

类型 主要用途
FBuildingCostTargetBase 自定义成本目标基类。
FBuildingCostTargetAmount 单个目标和数量。
FBuildingCostEntry 同一 Evaluator 处理的一组成本。
FBuildingCostContext 成本操作的运行时上下文。
FBuildingCostResult 检查或消耗结果。
FBuildingCostLine UI 成本行。
FBuildingRequirementLine UI 要求行。
FBuildingBuildCheckResult 完整 UI 评估结果。
UBuildingCostEvaluator 项目自定义成本处理器。
UBuildingCostSet 建筑成本配置资产。

相关文档