Working with Source Code (UE C++)
Warning
The source code for Unreal Engine requires a plugin to be installed to function. If you get compilation errors, make sure the plugin is installed and enabled.
Accessing game data during runtime is possible by utilizing the generated source code.
This section provides examples using default class names, but it is possible to customize class names during the source code generation process. Additionally, this customization allows to avoid naming collisions with existing code.
Loading Game Data
The following C++ code creates UGameData class and loads your game data into memory.
IFileManager& FileManager = IFileManager::Get();
const FString GameDataFilePath = TEXT("./RpgGameData.gdjs"); // or .json
const TUniquePtr<FArchive> GameDataStream = TUniquePtr<FArchive>(FileManager.CreateFileReader(*GameDataFilePath, EFileRead::FILEREAD_None));
UGameData* GameData = NewObject<UGameData>();
FGameDataLoadOptions Options;
Options.Format = EGameDataFormat::Json;
// Options.Patches.Add(PatchStream1);
// Options.Patches.Add(PatchStream2);
// ...
if (!GameData->TryLoad(GameDataStream.Get(), Options))
{
// Handle failure
}
The file RpgGameData.gdjs could be published game data or original database file (.gdjs or .gdmp).
Accessing Documents
You can access your documents as a list:
auto AllHeroes = GameData->AllHeroes // -> TMap<string, UHero>
auto Heroes = GameData->Heroes // -> TMap<string, UHero>
Settings schemas are accessed by name:
auto StartingHeroes = GameData->StartingSet.Heroes; // -> TMap<string, UHero>
Formulas
Formulas are supported when the plugin has the CHARON_FEATURE_FORMULAS_V2=1 compilation
constant enabled (available since plugin version 2025.2.x).
Each formula property in your schema generates a dedicated UObject subclass — for example
a property named LevelUpConditionsCheck with return type System.Boolean and one parameter
stats of type UObject produces:
// Formula Signature: (UObject stats) -> System.Boolean
UCLASS(BlueprintType)
class ULevelUpConditionsCheckFormula : public UObject
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
bool Invoke(UObject* Stats) const;
};
The generated Invoke method is BlueprintCallable, so it is usable both from C++ and
from Blueprint graphs without any additional work.
Calling a Formula
Formula properties are stored as UPROPERTY pointers on the owning document. Call
Invoke with the required arguments to evaluate the expression:
UHeroStats* Stats; // context for level condition checks
UHero* Hero = GameData->AllHeroes.FindRef(TEXT("hero_01"));
if (Hero && Hero->LevelUpConditionsCheck)
{
// for example formula is: Stats.Experience >= this.Levels[Stats.Level].ExperienceToLevelUp
// where `this` is a reference to the `UHero` document.
bool bCheckResult = Hero->LevelUpConditionsCheck->Invoke(Stats /* UObject* Stats */);
}
If the formula’s expression tree is missing, or if evaluation fails at runtime, Invoke
logs an error to the formula’s dedicated log category and returns the default value for the
return type (e.g. false for bool, 0 for numeric types).
Formula Scope
Every formula expression has two implicit identifiers available without a qualifier:
this— the document instance that declares the formula property. For a formula property defined on theHeroschema,thisrefers to theUHeroobject being evaluated.GameData— the rootUGameDatainstance, giving access to all other documents and settings.
Consider a Hero schema with a numeric property BaseDamage and a formula property
DamageFormula with signature (int32 Multiplier) -> int32. The formula expression
can reference this.BaseDamage directly:
this.BaseDamage * Multiplier
When Hero->DamageFormula->Invoke(/* Multiplier */ 5) is called on a Hero whose BaseDamage is 10, the expression
evaluates 10 * 5 and returns 50.
Formula Syntax
Formula expressions use C# 3.5 syntax with several extensions:
?.— null-conditional member access (this.Target?.Health)?[— null-conditional index access (list?[0])??— null-coalescing operator (value ?? 0)**— exponentiation operator (base ** exponent)
The following C# features are not supported:
Lambda expressions (
x => expr) — see below.Generic type arguments (
SomeMethod<T>()) — type arguments cannot be specified explicitly.
Member and method dispatch is dynamic: property and method names are resolved at
evaluation time against the actual UObject (or UStruct) instance passed as an
argument. Any UObject that has an Invoke(...)
UFUNCTION is treated as a callable. This means type mismatches surface at runtime
rather than at compile time.
Supported value types are the standard Blueprint primitives (bool, int32, int64,
float, double, FString, FText, FTimespan, FDateTime) plus any
UObject* and UStruct registered with Unreal Engine’s reflection system.
Lambda Expressions
Lambda expressions (x => expr, (x, y) => expr) are parsed but are not
implemented — calling Invoke on a formula that contains a lambda returns the default
value and logs an UnsupportedExpression error.
Generated Code Contract
Document properties are declared as public UPROPERTY fields and collections as
TArray<T*> / TMap<FString, T*>. These are intentionally mutable for two reasons:
Blueprint compatibility — Blueprint nodes read and write
UPROPERTYfields directly; getter-only accessors are not reachable from Blueprints.UObject lifecycle — UE’s garbage collector tracks references through
UPROPERTYmetadata, which requires fields to be declared in the standard way.
Treat the loaded data as logically read-only even though the language does not
enforce it. Do not assign to, replace, or clear any field or collection on a document
obtained from a loaded UGameData instance — mutating loaded data produces undefined
behaviour and is not persisted to the source file.
Note
To add derived or cached per-document state, subclass the relevant document class or
keep a separate runtime data structure. Do not write to the generated fields after
TryLoad returns.
Extension of Generated Code
Customizing Metadata
You can append additional or replace existing macro to the generated classes and their properties by modifying the Specification field of the related schema or property.
Metadata annotations are specified using the uecppAttribute key in the Specification string, which uses the application/x-www-form-urlencoded format.
To help construct the correct value, you can use a spreadsheet formula (e.g., in Excel or Google Sheets):
# Place your attribute in cell A1
=TEXTJOIN("&", 1, IF(ISBLANK(A1), "", "&uecppAttribute=" & ENCODEURL(A1)))
Alternatively, use JavaScript to generate the encoded string:
const params = new URLSearchParams();
params.append("uecppAttribute", "UPROPERTY(EditAnywhere, Meta = (Bitmask))");
console.log(params.toString());
// → uecppAttribute=UPROPERTY%28EditAnywhere%2C+Meta+%3D+%28Bitmask%29%29
After obtaining the encoded string, append it to the existing Specification value.
Example:
# Original Specification value:
icon=material&group=Metadata
# New attribute to add:
uecppAttribute=UCLASS%28BlueprintType%29
# Final Specification value:
icon=material&group=Metadata&uecppAttribute=UCLASS%28BlueprintType%29
These metadata annotations will be emitted directly into the generated C++ code, attached to the appropriate class or property.