← SEARCHABLE ARCHIVE
Unreal Engine · 2026-07-10

Extending your skills with DataTable and UObject

How to separate numerical data from complex gimmicks

INTERACTIVE READING MODE →

The articles written on this blog were created with the goal of teaching. Also, the information in the article may be incorrect, so please be careful.

If you write all the stats and characteristics for each unit in a C++ constructor, you will have to rebuild them every time you change the balance. ProjectTB separates numerical data from complex behavior.

Simple numbers are DataTable

Values ​​that can be expressed in rows and columns, such as physical strength by level, attack power, and required experience, are placed in the DataTable.

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Progression")
TObjectPtr<UDataTable> UnitProgressionTable;

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Progression")
TObjectPtr<UDataTable> UnitTraitTable;

Even if planning values ​​change, C++ logic can remain the same. However, if you try to express all actions with just name strings and numbers, the conditional statement becomes huge.

The complex gimmick is UObject

ProjectTB'sUTBUnitSkillclassUTBUnitTraitis a replaceable UObject.

UFUNCTION(BlueprintNativeEvent)
bool Activate(ATBUnitBase* TargetUnit, ATBHexTile* TargetTile);

UFUNCTION(BlueprintNativeEvent)
int32 ModifyOutgoingDamage(
    ATBUnitBase* TargetUnit,
    int32 Damage
) const;

For each attribute, the events before and after damage, recovery, action start and end, and kill events can be overridden.

DataTableTraitClassRecord which UObject class to create.

DataTable
Name/Description/Numerical/TraitClass
                    ↓
UTBUnitTrait derived classes
Actual gimmick execution

DataTable manages the data and UObject encapsulates the behavior. By mixing the two methods, there is no need to create a class for simple numerical characteristics, and there is no need to put complex characteristics in a huge switch statement.