Ue Data Driven Design logo

Ue Data Driven Design

Community
kevinpbuckley
ue-data-driven-design

Drive Unreal gameplay from externally-editable data instead of hardcoded values — DataTables (UDataTable, FTableRowBase, CSV/JSON import, UCompositeDataTable), DataAssets (UDataAsset, UPrimaryDataAsset with AssetManager), Curves (UCurveFloat, UCurveTable, FRuntimeFloatCurve), config-driven UPROPERTY(config) in .ini files, and DeveloperSettings (UDeveloperSettings) for project-wide tuning. Use when defining item/enemy/level/balance schemas, choosing the right data container, exposing designer-tunable values, replacing magic numbers with editable assets, or layering data across DLC/platforms with composite tables.

Overview

Publisherkevinpbuckley
Repositoryunreal-engine-skills
Skill nameue-data-driven-design
Stars
89
Forks
9
Bundled files
4
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 4 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by kevinpbuckley on GitHub. Read the source before you install it.

Installation

Install the Ue Data Driven Design AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/kevinpbuckley/unreal-engine-skills/tree/master/skills/core/ue-data-driven-design
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/kevinpbuckley/unreal-engine-skills.git /tmp/unreal-engine-skills
mkdir -p .claude/skills
cp -r /tmp/unreal-engine-skills/skills/core/ue-data-driven-design .claude/skills/ue-data-driven-design
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Ue Data Driven Design in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Ue Data Driven Design on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Ue Data Driven Design is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Data-driven design

Hardcoding gameplay values (item stats, enemy configs, balance numbers, curves) makes iteration slow and risky. Move them into assets and config objects that designers can edit without recompiling. The choice of container drives every downstream workflow.

When to use this skill

  • Defining sets of similar records (items, enemies, weapons, abilities, loot).
  • One-off structured config objects (boss setup, game-mode tuning, single-character stats).
  • Values that vary over an input (damage falloff, XP per level, camera ease curves).
  • Replacing magic numbers with .ini-backed project settings editable in Project Settings.
  • Layering or overriding rows across game modes, DLC, or platforms (composite tables).

Pick the right container

NeedUse
Many rows of the same schema, bulk spreadsheet workflowUDataTable
Layered/overriding rows across DLC or variantsUCompositeDataTable
A single rich config object, possibly subclassedUDataAsset / UPrimaryDataAsset
A value that depends on another (falloff, curves)UCurveFloat / UCurveTable
An inline editable curve inside a struct/componentFRuntimeFloatCurve
Global programmer-near settings in .iniUCLASS(Config=X) + UPROPERTY(config)
Project Settings panel entry with change notificationsUDeveloperSettings

DataTables — tabular records

Define a row struct inheriting FTableRowBase, then create a DataTable asset in the Content Browser (or import CSV/JSON). The table stores rows as a TMap<FName, uint8*> internally, accessed through typed template helpers.

cpp
// ItemRow.h — one USTRUCT per table schema
USTRUCT(BlueprintType)
struct FItemRow : public FTableRowBase
{
    GENERATED_BODY()
    UPROPERTY(EditAnywhere, BlueprintReadWrite) FText  DisplayName;
    UPROPERTY(EditAnywhere, BlueprintReadWrite) int32  Price    = 0;
    UPROPERTY(EditAnywhere, BlueprintReadWrite) float  Weight   = 1.f;
    UPROPERTY(EditAnywhere, BlueprintReadWrite) TSoftObjectPtr<UTexture2D> Icon;
};
cpp
// Runtime lookup — context string appears in log if the row is missing
if (const FItemRow* Row = ItemTable->FindRow<FItemRow>(TEXT("Sword_Iron"), TEXT("ItemQuery")))
{
    float w = Row->Weight;
}

// Iterate every row
ItemTable->ForeachRow<FItemRow>(TEXT("PopulateShop"),
    [](const FName& Key, const FItemRow& Row) { /* ... */ });

// Typed bulk access
TArray<FItemRow*> All;
ItemTable->GetAllRows<FItemRow>(TEXT("All"), All);

Key macro rule: the struct needs USTRUCT(BlueprintType) so Blueprint graphs can read rows; FTableRowBase is the mandatory base (DataTable.h:33).

FDataTableRowHandle (DataTable.h:424) — a two-field struct (table + row name) you expose as a UPROPERTY so designers pick the exact row in the Details panel, eliminating string typos.

cpp
UPROPERTY(EditAnywhere, BlueprintReadWrite) FDataTableRowHandle RewardRow;
// At runtime:
if (const FItemRow* R = RewardRow.GetRow<FItemRow>(TEXT("Reward"))) { ... }

UCompositeDataTable (CompositeDataTable.h:13) — a UDataTable subclass that stacks parent tables; higher-index parents win on duplicate row names. Use for DLC or per-platform row overrides without duplicating the base table. See references/datatables-and-composite.md.

DataAssets — structured config objects

A UDataAsset is a UObject subclass you create as an asset. Inherit it for rich single-record configs; override properties in Blueprint Data Only subclasses for per-instance variation.

cpp
// EnemyConfig.h
UCLASS(BlueprintType)
class MYGAME_API UEnemyConfig : public UPrimaryDataAsset
{
    GENERATED_BODY()
public:
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Stats")
    float MaxHealth = 100.f;

    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Spawning")
    TSoftClassPtr<APawn> PawnClass;

    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tags")
    FGameplayTagContainer Traits;
};
  • UDataAsset (DataAsset.h:17) — base; creates assets in the Content Browser, hard-loaded when the outer object is loaded.
  • UPrimaryDataAsset (DataAsset.h:47) — adds GetPrimaryAssetId() for UAssetManager discovery, async loading, and bundle-based streaming. Use when you need lifecycle control or have many instances (hundreds of items). See ue-asset-management.

Reference instances as TObjectPtr<UEnemyConfig> (hard, loads immediately) or TSoftObjectPtr<UEnemyConfig> (lazy, loaded on demand). DataAssets beat DataTables when each record needs inheritance, rich nested types, or Blueprint subclassing.

See references/data-assets-and-validation.md.

Curves

Use curves when a value depends on a continuous input (time, distance, level).

TypeStorageEvaluation
UCurveFloatstandalone assetCurve->GetFloatValue(X)
UCurveTablemany named curves in one assetTable->FindRichCurve(Name, Context)
FRuntimeFloatCurveembedded in a struct/componentCurve.GetRichCurve()->Eval(X)
cpp
// Standalone curve asset property
UPROPERTY(EditAnywhere, Category="Balance") TObjectPtr<UCurveFloat> DamageFalloff;

float GetDamage(float Distance) const
{
    return BaseDamage * (DamageFalloff ? DamageFalloff->GetFloatValue(Distance) : 1.f);
}
cpp
// Inline curve — editable in the Details panel without a separate asset
UPROPERTY(EditAnywhere, Category="Motion") FRuntimeFloatCurve SpeedOverTime;

float GetSpeed(float T) const
{
    const FRichCurve* C = SpeedOverTime.GetRichCurveConst();
    return C ? C->Eval(T) : 0.f;
}

UCurveFloat (CurveFloat.h:30) wraps a FRichCurve and is the standard designer-facing single-axis float curve. FRuntimeFloatCurve (CurveFloat.h:12) lets you bake the curve inline or point at an external UCurveFloat asset.

See references/curves-and-runtime-data.md.

Config-driven properties (.ini files)

For global, programmer-near defaults that ship with the project, mark the class and properties:

cpp
// Reads/writes Config/DefaultGame.ini under [/Script/MyGame.UGameBalanceSettings]
UCLASS(Config=Game, DefaultConfig)
class MYGAME_API UGameBalanceSettings : public UObject
{
    GENERATED_BODY()
public:
    UPROPERTY(Config, EditAnywhere, Category="Balance")
    float GlobalDamageScale = 1.f;

    UPROPERTY(Config, EditAnywhere, Category="Economy")
    int32 StartingGold = 500;
};

// Read anywhere:
const UGameBalanceSettings* S = GetDefault<UGameBalanceSettings>();
float Scale = S->GlobalDamageScale;

The .ini section name is [/Script/ModuleName.ClassName] (without the U prefix). DefaultConfig writes user edits back to Default<Category>.ini rather than a per-user file. Do not use this pattern for content-scale data (hundreds of records); use DataTables/DataAssets.

DeveloperSettings — Project Settings panel entries

UDeveloperSettings (DeveloperSettings.h:23, module DeveloperSettings) auto-discovers the class and adds it to Project Settings. Ideal for cross-system tuning knobs and references to key data assets that the rest of the codebase needs to find.

cpp
UCLASS(Config=Game, DefaultConfig, meta=(DisplayName="My Game Settings"))
class MYGAME_API UMyGameSettings : public UDeveloperSettings
{
    GENERATED_BODY()
public:
    UMyGameSettings() { CategoryName = TEXT("Game"); SectionName = TEXT("MyGameSettings"); }

    UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="Tables")
    TSoftObjectPtr<UDataTable> ItemTable;

    UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="Tuning")
    float DifficultyMultiplier = 1.f;

    // Convenience accessor
    static const UMyGameSettings* Get() { return GetDefault<UMyGameSettings>(); }
};
cpp
// Consuming code — no FindObject, no hard path
const UDataTable* Table = UMyGameSettings::Get()->ItemTable.LoadSynchronous();

Add DeveloperSettings to your module's PublicDependencyModuleNames in Build.cs.

See references/config-and-developer-settings.md.

Validation

Override IsDataValid on DataAssets and in row structs to surface content errors before runtime.

cpp
// In UEnemyConfig (editor-only)
#if WITH_EDITOR
virtual EDataValidationResult IsDataValid(FDataValidationContext& Context) const override
{
    EDataValidationResult Result = Super::IsDataValid(Context);
    if (MaxHealth <= 0.f)
        Context.AddError(FText::FromString(TEXT("MaxHealth must be > 0")));
    if (PawnClass.IsNull())
        Context.AddError(FText::FromString(TEXT("PawnClass is not set")));
    return Context.GetNumErrors() > 0 ? EDataValidationResult::Invalid : Result;
}
#endif

Run validation from the Content Browser (Asset Actions → Validate Assets) or via UnrealEditor-Cmd.exe MyProject.uproject -run=DataValidation for CI. The Data Validation plugin calls IsDataValid on UDataTable itself (engine implementation) and on UObject-derived assets that override it.

Gotchas

  • Wrong container shape — large flat datasets in individual DataAssets, or deeply nested configs forced into DataTable rows — match the shape to the tool.
  • Hard refs to heavy assets in rows/assets — every row's hard ref loads at table load time; use TSoftObjectPtr for textures, meshes, sounds, and class refs.
  • Row name typos in FindRow return null silently (with a log warning); prefer FDataTableRowHandle pickers so designers pick from a validated list.
  • Forgetting USTRUCT(BlueprintType) on a row struct — Blueprint nodes that read rows will fail to expose the type.
  • Editing CSV after adding struct fields — the column order and header names must match the struct; add new fields at the end and re-import.
  • Composite table loop — UCompositeDataTable detects and rejects circular parent references at load time, but keep the parent chain shallow.
  • UDeveloperSettings not showing — the module must be listed in PublicDependencyModuleNames; also check that CategoryName maps to a known Project Settings category ("Game", "Engine", "Editor").
  • GetDefault<T>() vs GetMutableDefault<T>() — GetDefault is read-only and safe anywhere; GetMutableDefault is for editor tooling or startup init only, never gameplay.
  • Config UPROPERTY for content data — .ini values are not asset-browser-visible and give designers a worse authoring experience; use DataTables or DataAssets for game content.

Version notes

  • UCompositeDataTable has been stable since UE4. The AppendParentTables/RemoveParentTable runtime API (CompositeDataTable.h:59–62) allows dynamic parent modification, but the comment in the header warns this can cause hitches during gameplay.
  • UDeveloperSettings is in its own module (DeveloperSettings) since UE5; in UE4 it was part of Engine. Update Build.cs accordingly.
  • FRuntimeFloatCurve::GetRichCurveConst() is the const accessor added in UE5 to avoid the const-correctness issues of the earlier mutable-only path.
  • FTableRowBase::IsDataValid signature matches UObject::IsDataValid(FDataValidationContext&) introduced in UE5.1; do not use the older TArray<FText>& variant.

References & source material

Engine source (UE 5.8, under Engine/Source/Runtime/):

  • Engine/Classes/Engine/DataTable.h — FTableRowBase:33, UDataTable:76, FindRow<T>:219, GetAllRows<T>:199, ForeachRow<T>:232, FDataTableRowHandle:424, FDataTableCategoryHandle:497.
  • Engine/Classes/Engine/CompositeDataTable.h — UCompositeDataTable:13, ParentTables:83, AppendParentTables:59.
  • Engine/Classes/Engine/DataAsset.h — UDataAsset:17, UPrimaryDataAsset:47, GetPrimaryAssetId():53.
  • Engine/Classes/Engine/CurveTable.h — UCurveTable:40, FindCurve:131, FindRichCurve:150, FCurveTableRowHandle:262.
  • Engine/Classes/Curves/CurveFloat.h — FRuntimeFloatCurve:12, UCurveFloat:30, GetFloatValue:44.
  • DeveloperSettings/Public/Engine/DeveloperSettings.h — UDeveloperSettings:23, GetContainerName:31, GetCategoryName:33, GetSectionName:35.

Official docs (UE 5.8):

Deep-dive references in this skill:

Related skills: ue-asset-management, ue-gameplay-tags, ue-project-structure, ue-cpp-fundamentals.

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Ue Data Driven Design AI skill do?

Drive Unreal gameplay from externally-editable data instead of hardcoded values — DataTables (UDataTable, FTableRowBase, CSV/JSON import, UCompositeDataTable), DataAssets (UDataAsset, UPrimaryDataAsset with AssetManager), Curves (UCurveFloat, UCurveTable, FRuntimeFloatCurve), config-driven UPROPERTY(config) in .ini files, and DeveloperSettings (UDeveloperSettings) for project-wide tuning. Use when defining item/enemy/level/balance schemas, choosing the right data container, exposing designer-tunable values, replacing magic numbers with editable assets, or layering data across DLC/platforms...

Why use Ue Data Driven Design on TypingMind?

Because you install it once and use it with any model. Ue Data Driven Design is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Ue Data Driven Design in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/kevinpbuckley/unreal-engine-skills/tree/master/skills/core/ue-data-driven-design. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Ue Data Driven Design?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Ue Data Driven Design?

As many as you like. As long as a model supports skills, you can use Ue Data Driven Design with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Ue Data Driven Design AI skill free?

It is published on GitHub by kevinpbuckley. Check the repository for licensing terms. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇