Building Cost Evaluator¶
UBuildingCostEvaluator is the extension point for the building cost system. It is used to integrate the plugin with the project's inventory, currency, attribute, or resource systems.
This is an abstract class and cannot be used directly. Projects must create a derived class in Blueprint or C++ and implement the cost validation, resource consumption, and UI evaluation logic.
Basic Information¶
| Item | Description |
|---|---|
| Class | UBuildingCostEvaluator |
| Base Class | UObject |
| Type | Abstract class |
| Blueprint Support | Supports inheritance and overriding |
| Primary Purpose | Integrates project-specific resource systems |
| Recommended State | Stateless |
| Actual Resource Consumption | Should be performed by the server |
Main Responsibilities¶
| API | Description |
|---|---|
CanAfford |
Checks whether the current cost can be paid. |
Consume |
Consumes the corresponding resources. |
EvaluateForUI |
Generates cost information for the building UI. |
Creating an Evaluator¶
Blueprint¶
Create a Blueprint derived from:
Then override the following functions as required:
C++¶
// Copyright 2026 Zhiying Li. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Cost/BuildingCostEvaluator.h"
#include "MyBuildingCostEvaluator.generated.h"
UCLASS()
class UMyBuildingCostEvaluator : public UBuildingCostEvaluator
{
GENERATED_BODY()
public:
virtual FBuildingCostResult CanAfford_Implementation(
const FBuildingCostContext& Context,
const FBuildingCostEntry& Entry
) const override;
virtual FBuildingCostResult Consume_Implementation(
const FBuildingCostContext& Context,
const FBuildingCostEntry& Entry
) const override;
virtual FBuildingBuildCheckResult EvaluateForUI_Implementation(
const FBuildingCostContext& Context,
const FBuildingCostEntry& Entry
) const override;
};
CanAfford¶
Checks whether the current player can pay the specified cost.
// Copyright 2026 Zhiying Li. All Rights Reserved.
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Building|Cost")
FBuildingCostResult CanAfford(
const FBuildingCostContext& Context,
const FBuildingCostEntry& Entry
) const;
| Type | Name | Data Type | Description |
|---|---|---|---|
| Param | Context |
const FBuildingCostContext& |
The runtime context required for the current cost check. |
| Param | Entry |
const FBuildingCostEntry& |
The cost entry processed by the current Evaluator. |
| Return | Result |
FBuildingCostResult |
Indicates whether the cost can be paid and includes the failure reason. |
CanAfford should only perform validation and must not modify runtime data.
Do not perform the following operations in this function:
- Remove inventory items
- Deduct currency
- Modify character attributes
- Modify shared storage
- Write other persistent data
Consume¶
Validates and consumes the specified cost.
// Copyright 2026 Zhiying Li. All Rights Reserved.
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Building|Cost")
FBuildingCostResult Consume(
const FBuildingCostContext& Context,
const FBuildingCostEntry& Entry
) const;
| Type | Name | Data Type | Description |
|---|---|---|---|
| Param | Context |
const FBuildingCostContext& |
The runtime context required for the current resource consumption. |
| Param | Entry |
const FBuildingCostEntry& |
The cost entry to consume. |
| Return | Result |
FBuildingCostResult |
Indicates whether consumption succeeded and includes the failure reason. |
Consume should check the available amount again before modifying resources.
Even if CanAfford was called earlier, the resource state may have changed. For example:
- The player performed another transaction
- Inventory items were removed
- The currency amount changed
- Shared storage was used by another player
In multiplayer games, actual resource consumption should be performed by the server.
EvaluateForUI¶
Generates cost information for the building UI.
// Copyright 2026 Zhiying Li. All Rights Reserved.
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Building|Cost")
FBuildingBuildCheckResult EvaluateForUI(
const FBuildingCostContext& Context,
const FBuildingCostEntry& Entry
) const;
| Type | Name | Data Type | Description |
|---|---|---|---|
| Param | Context |
const FBuildingCostContext& |
The runtime context used for UI evaluation. |
| Param | Entry |
const FBuildingCostEntry& |
The cost entry to display. |
| Return | Result |
FBuildingBuildCheckResult |
The cost display data and current build availability. |
This function can generate:
- Cost name
- Required amount
- Current amount
- Whether the requirement is satisfied
- Insufficient-resource messages
- Building failure information
EvaluateForUI should only read data and generate display information. It must not consume or modify resources.
API Responsibilities¶
| API | Checks Resources | Modifies Resources | Generates UI Data |
|---|---|---|---|
CanAfford |
Yes | No | Optional |
Consume |
Yes | Yes | No |
EvaluateForUI |
Yes | No | Yes |
Related Data Types¶
| Type | Description |
|---|---|
FBuildingCostContext |
Provides the player, world, and project runtime objects. |
FBuildingCostEntry |
Describes the cost that must be validated or consumed. |
FBuildingCostResult |
Indicates whether validation or consumption succeeded. |
FBuildingBuildCheckResult |
Contains the UI cost evaluation and building validation result. |
Evaluator State¶
Evaluators should generally remain stateless.
Runtime information should be obtained from FBuildingCostContext, such as:
- Player Controller
- Player State
- Pawn
- Inventory Component
- Currency Component
- Project-specific resource manager
Cost targets and amounts should be obtained from FBuildingCostEntry.
It is not recommended to retain the following in an Evaluator:
- Player object references
- Inventory Component references
- The current Cost Entry
- The current building data
- The previous validation result
- World Actor references
This prevents incorrect state from being shared between different players or building operations.
Registering an Evaluator¶
An Evaluator can be used in either of the following ways:
| Method | Description |
|---|---|
| Assigned directly to a Cost Entry | The current cost entry uses the specified Evaluator. |
| Project default rule | The Evaluator is resolved from Default Evaluators according to the cost type. |
Project-default Evaluators are configured under:
For cost system configuration, see Building Cost System.
Blueprint Implementation Notes¶
| API | Requirement |
|---|---|
CanAfford |
Read resources only and return the validation result. |
Consume |
Validate the resources again, then perform consumption. |
EvaluateForUI |
Generate cost text and failure information without modifying resources. |
A Blueprint Evaluator should use Context to locate the resource components associated with the current player instead of using a fixed player or global object.
Multiplayer¶
| Operation | Recommended Execution Location |
|---|---|
| UI cost evaluation | Local client |
| Local affordability pre-check | Local client |
| Final cost validation | Server |
| Actual resource consumption | Server |
| Building creation | Server |
Client-side validation results are used only for UI display and local feedback.
The server must perform cost validation again and must not directly trust the result submitted by the client.
Troubleshooting¶
| Issue | What to Check |
|---|---|
| The building always reports insufficient resources | Check whether Context can locate the correct resource object for the current player. |
| Costs are not displayed in the UI | Check whether EvaluateForUI is implemented. |
| The building can be created but resources are not deducted | Check whether the server calls Consume. |
| Resources are deducted multiple times for one building | Check whether Consume is executed only during the server confirmation stage. |
| Validation succeeds but consumption fails | The resource state may have changed between the two calls. |
| Different players read the same resource data | Check whether the Evaluator incorrectly retains a player reference. |
| A Blueprint Evaluator cannot be created | Check whether Building Cost Evaluator was selected as the parent class. |
| The corresponding Evaluator cannot be found | Check the Cost Entry or Default Evaluators configuration. |