ProjectDefinitionGenerator

July 15, 2026 ยท View on GitHub

Integrated JSON-to-DataAsset generator for Project definition types (items, objects, abilities, and capabilities).

Editor-only plugin for turning text-based definitions into generated Unreal assets.

Integration Boundary

This is not a standalone or drop-in plugin. It is one stage of an integrated Project plugin suite. To reuse it in another Unreal project, copy this plugin together with every first-party dependency declared by its ProjectDefinitionGenerator.uplugin, including the transitive dependencies declared by those plugins. Enable the listed Unreal Engine plugins, regenerate project files, and compile the target project before running generation.

For the full three-stage workflow, also install ProjectAssetSync and ProjectPlacementEditor with their declared dependencies. The .uplugin descriptors are the dependency source of truth; do not maintain a separate copied module list. A distribution is ready only after this route compiles and completes a sample JSON-to-DataAsset generation in a clean project.

Overview

This editor plugin provides a data-driven approach to generating UDataAsset definitions from JSON source files. Resource plugins only provide:

  • Runtime definition class (e.g., UObjectDefinition)
  • Source JSON data files
  • JSON Schema with x-alis-generator extension block

The generator handles all logic: parsing, field mapping, incremental generation, orphan cleanup.

Data Pipeline Role

This plugin handles GENERATION - one-way transformation with validation (JSON -> DataAsset).

NOT in scope:

How it fits in the pipeline:

  1. SYNC: Asset renamed -> JSON paths updated -> Redirectors fixed
  2. GENERATION (this plugin): JSON changed -> DataAsset regenerated -> Broadcasts OnDefinitionRegenerated
  3. PROPAGATION: Definition changed -> Scene actors updated

See: Data Pipeline Architecture for complete flow documentation.

Architecture

+---------------------------+
|  Resource Plugin          |
|  (ProjectObject, etc.)    |
|                           |
|  Data/                    |
|    Schemas/               |
|      object.schema.json   |  <- x-alis-generator block defines type
|    Objects/               |
|      Template/            |
|        door.json          |  <- SOT (Source of Truth)
|                           |
|  Content/Objects/         |
|    Template/              |
|      door.uasset          |  <- Generated DataAsset
+---------------------------+
         |
         v
+---------------------------+
| ProjectDefinitionGenerator|
|                           |
| DiscoverAndRegisterManifests()
|   -> Scans *.schema.json  |
|   -> Parses x-alis-generator
|   -> Registers type       |
|                           |
| GenerateAllForType()      |
|   -> Finds JSON files     |
|   -> Hash comparison      |
|   -> Creates/updates assets
|   -> Preserves folder hierarchy
+---------------------------+

Usage

Add x-alis-generator block to your JSON schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Object Definition",

  "x-alis-generator": {
    "TypeName": "Object",
    "DefinitionClass": "/Script/ProjectObject.ObjectDefinition",
    "SourceSubDir": "",
    "GeneratedContentPath": "/ProjectObject/Objects",
    "IdPropertyName": "ObjectId",
    "GeneratorVersion": 1,

    "FieldMappings": [
      { "JsonPath": "displayName", "PropertyName": "Data.DisplayName", "FieldType": "Text", "bRequired": true },
      { "JsonPath": "world.staticMesh", "PropertyName": "WorldStaticMesh", "FieldType": "SoftObject" }
    ]
  },

  "type": "object",
  "properties": { ... }
}

The generator auto-discovers schemas from Plugins/**/Data/Schemas/*.schema.json.

Manual Registration (C++)

FDefinitionTypeInfo TypeInfo;
TypeInfo.DefinitionClass = UObjectDefinition::StaticClass();
TypeInfo.PluginName = TEXT("ProjectObject");
TypeInfo.SourceSubDir = TEXT("");
TypeInfo.GeneratedContentPath = TEXT("/ProjectObject/Objects");
TypeInfo.IdPropertyName = TEXT("ObjectId");
TypeInfo.GeneratorVersion = 1;

TypeInfo.FieldMappings = {
    { TEXT("displayName"), TEXT("Data.DisplayName"), EDefinitionFieldType::Text, true },
    { TEXT("world.staticMesh"), TEXT("WorldStaticMesh"), EDefinitionFieldType::SoftObject }
};

UDefinitionGeneratorSubsystem::Get()->RegisterDefinitionType(TEXT("Object"), TypeInfo);

Triggering Generation

Editor Menu: Tools -> Project Definition Generator -> Generate All

Commandlet:

UnrealEditor-Cmd.exe YourProject.uproject -run=GenerateDefinitions -nopause

C++ API:

auto* Generator = UDefinitionGeneratorSubsystem::Get();
Generator->DiscoverAndRegisterManifests();
Generator->GenerateAll(bForceRegenerate);

Field Types

FieldTypeJSON ValueUProperty Type
AutoanyAuto-detected from reflection
StringstringFString
NamestringFName
TextstringFText (localized)
Intnumberint32
Floatnumberfloat/double
Boolbooleanbool
Vector{x,y,z}FVector
Rotator{pitch,yaw,roll}FRotator
IntPoint{x,y}FIntPoint
SoftObjectstring (path)TSoftObjectPtr
SoftClassstring (path)TSoftClassPtr (adds _C suffix)
GameplayTagstringFGameplayTag
GameplayTagContainerarray of stringsFGameplayTagContainer
SoftObjectArrayarray of stringsTArray
SoftClassArrayarray of stringsTArray
GameplayTagFloatMap{"Tag.Name": value}TMap<FGameplayTag, float>

Features

Incremental Generation

Assets are only regenerated when:

  • JSON file hash changes
  • Generator version increases
  • Force regenerate flag is set

Each generated asset stores:

  • SourceJsonHash - MD5 of normalized JSON
  • GeneratorVersion - Version from schema
  • SourceJsonPath - Relative path for orphan tracking
  • bGenerated - Flag indicating auto-generation

Folder Hierarchy Preservation

Source JSON folder structure is mirrored to generated Content:

Data/Objects/Template/door.json
    -> /ProjectObject/Objects/Template/door.uasset

Orphan Cleanup

When JSON files are moved/renamed/deleted:

Generator->CleanupOrphanedAssets(TEXT("Item"));

Compares SourceJsonPath metadata against existing JSON files.

Nested Property Paths

Both JSON paths and property names support dot notation:

{ "JsonPath": "world.staticMesh", "PropertyName": "Data.WorldVisual.StaticMesh" }

x-alis-generator Block Reference

FieldRequiredDefaultDescription
TypeNameYes-Unique type name (e.g., "Item")
DefinitionClassYes-Full class path
GeneratedContentPathYes-Content path for generated assets
PluginNameNoInferredPlugin name for FProjectPaths
SourceSubDirNo""Subdirectory within Data/
IdPropertyNameNo"Id"Property name for asset ID
GeneratorVersionNo1Increment on schema changes
HashPropertyNameNo"SourceJsonHash"Property for hash storage
VersionPropertyNameNo"GeneratorVersion"Property for version storage
GeneratedFlagPropertyNameNo"bGenerated"Property for generated flag
SourcePathPropertyNameNo"SourceJsonPath"Property for source path
FieldMappingsNo[]Array of field mapping objects

FieldMapping Object

FieldRequiredDefaultDescription
JsonPathYes-JSON key path (e.g., "world.staticMesh")
PropertyNameYes-UProperty name (e.g., "Data.WorldMesh")
FieldTypeNo"Auto"Type hint for parsing
bRequiredNofalseFail if field missing

Definition Class Requirements

Your definition class should have these metadata properties:

UCLASS(BlueprintType)
class UObjectDefinition : public UPrimaryDataAsset
{
    GENERATED_BODY()

public:
    // ID field (name configurable via IdPropertyName)
    UPROPERTY(EditAnywhere, AssetRegistrySearchable)
    FName ObjectId;

    // Generator metadata (names configurable)
    UPROPERTY(VisibleAnywhere, Category = "Generator")
    bool bGenerated = false;

    UPROPERTY(VisibleAnywhere, Category = "Generator")
    int32 GeneratorVersion = 0;

    UPROPERTY(VisibleAnywhere, Category = "Generator")
    FString SourceJsonPath;

    UPROPERTY(VisibleAnywhere, Category = "Generator")
    FString SourceJsonHash;

    // Your data fields...
};

Adding a New Definition Type

  1. Create definition class in your resource plugin
  2. Add generator metadata properties (bGenerated, SourceJsonHash, etc.)
  3. Create JSON schema in Data/Schemas/<type>.schema.json
  4. Add x-alis-generator block with field mappings
  5. Create source JSON files in Data/<Type>/
  6. Run generator (menu or commandlet)

Extending Field Types

If your type needs complex parsing not covered by EDefinitionFieldType:

  1. Add new enum value to EDefinitionFieldType in DefinitionTypeInfo.h
  2. Add parsing logic to SetPropertyFromJson() in DefinitionGeneratorSubsystem.cpp
  3. Update StringToFieldType() for schema parsing

Or use CustomParser delegate for one-off complex types.

File Structure

ProjectDefinitionGenerator/
  Source/ProjectDefinitionGenerator/
    Public/
      DefinitionTypeInfo.h           <- FDefinitionTypeInfo, EDefinitionFieldType
      DefinitionGeneratorSubsystem.h <- Main generator subsystem
      GenerateDefinitionsCommandlet.h
    Private/
      DefinitionGeneratorSubsystem.cpp
      DefinitionGeneratorMenuExtension.cpp  <- Editor menu integration
      GenerateDefinitionsCommandlet.cpp
  ProjectDefinitionGenerator.uplugin
  README.md

Required ALIS Plugin Dependencies

  • ProjectCore
  • ProjectEditorCore
  • ProjectObject
  • ProjectObjectCapabilities
  • ProjectGAS

These are the direct plugin dependencies declared by the descriptor. Their descriptors own the transitive dependency closure.

Bundled Unreal Engine Prerequisites

  • GameplayAbilities

Engine plugins ship with Unreal Engine and only need to be enabled. They are prerequisites, not separate ALIS downloads.

See Also

Note:

  • the public mirror includes source JSON and schemas under plugin Data/ folders
  • generated .uasset files and other binary project assets are intentionally excluded; run the generator in Unreal Editor to produce them