WorldForge Studio

07 — Export & Engine Targets

A world authored in WorldForge Studio exports to Godot, Unity, Unreal, Adventure Craft, Foundry VTT, Bevy, and a mobile companion app — with one click. The export is lossy on rendering, lossless on data: every gameplay, terrain, biome, object, NPC, and quest reference round-trips back into the GAS-native world document.


0. Target status (refreshed 2026-09-06)

TargetStatusDepthNotes
.gas-world JSON✅ SHIPPEDFull round-tripCanonical interchange; deterministic serializeWorld + deserializeWorld in packages/world-engine. Export via <ExportMenu> (phase-1-closeout-complete, 2026-08-19); import via <ImportWorldButton> (file picker → Y.Doc seed → route, landed 2026-08-20 ae9cf97).
Godot 4.4+✅ SHIPPED (MVP)Geometry primitiveNode2D root + Marker2D per cell + Marker2D per object with metadata. Renders in Godot 4.4+; real TileMapLayer upgrade is a follow-up. Validated against Godot 4.6.1 headless.
Adventure Craft✅ SHIPPED (MVP)Export + import round-tripexportAdventureCraft + importAdventureCraft in packages/export/src/adventure-craft.ts; hex + square fixtures round-trip structurally. Live multiplayer bridge (Phase 4 M4.9 / Phase 5 M5.11) ❌.
Unity✅ MVP shipped 2026-08-22exportUnity(world) → { 'world.wme-unity.json', 'README.md' } in packages/export/src/unity.ts. Wired into ExportMenu. Portable JSON (schemaVersion: '0.1') — companion MonoBehaviour deserialises via Newtonsoft.Json and spawns GameObjects at Awake.Follow-ups: native .unitypackage bundler + Addressables-key hints.
Unreal✅ MVP shipped 2026-08-22exportUnreal(world) → { 'world.wme-unreal.json', 'README.md' } in packages/export/src/unreal.ts. Wired into ExportMenu. Portable JSON with grid.tileSize pre-converted to Unreal units (worldTileSize m × 100 UU/m). Consumer UWorldForgeLoader uses FJsonObjectConverter + TSoftObjectPtr<UStaticMesh> for asset resolution.Follow-ups: .uplugin scaffold + soft-ref catalog.
Foundry VTT✅ MVP shipped 2026-08-22exportFoundry(world) → { 'scene.json', 'world.wme-foundry.json', 'README.md', 'journal.json'? } in packages/export/src/foundry.ts. Wired into ExportMenu. scene.json is a native Foundry v11+ scene (grid.type mapped from projection + hex orientation; walls from region polygons; notes at POI anchors; placeholder tokens per named slot). Portable payload mirrors the Bevy schema for a companion module. Lore (0.24.0): journal.json (JournalEntry per pantheon / faith / school / faction + Spellbook + Myths; deterministic _ids, import with createDocuments(data, { keepId: true })) and POI notes carry entryId of their faith's / pantheon's / school's journal.Follow-ups: tiles[] from biome atlas; token-actor binding hints.
Bevy✅ MVP shipped 2026-08-22exportBevy(world) → { 'world.wme-bevy.json', 'README.md' } in packages/export/src/bevy.ts. Wired into the editor's ExportMenu. Portable JSON schema (schemaVersion: '0.1') — companion plugin (bevy-game-editor) deserialises into ECS entities.Follow-ups: native .scn.ron emitter once the plugin's component graph stabilises.
Mobile companion❌ Not started—Phase 8 M8.4.

Canonical export contract (all shipped targets):

export<Target>(world: World, options?: <Target>Options): ExportResult

interface ExportResult {
  files: ReadonlyMap<string, string | Uint8Array>;
  warnings: readonly Warning[];
}

Every export function is pure; the launcher UI (<ExportMenu> in the editor header) wraps files in a Blob and triggers a download at the edge.

All six engine targets are shipped as of 2026-08-22 (Bevy PR #39, Foundry PR #40, Unity + Unreal PR #41, on top of Godot + Adventure Craft from phase-1-closeout-complete), every one reachable from the editor's <ExportMenu>. Bevy / Unity / Unreal / Foundry all use the portable-JSON pattern (world.wme-<engine>.json + README.md, consumed by a companion loader in the target engine) rather than native project files — engine GUIDs / actor IDs are per-project, so a native bundle is deferred until each companion stabilises. Foundry additionally emits a native v11+ scene.json. packages/export has a CI coverage gate (PR #86).

For the MVP-shipped Godot output shape, see §2 below. Sections 3–7 still describe the intended native shape for Unity / Unreal / Foundry / Bevy; the shipped MVPs are the portable-JSON subset — treat those sections as the follow-up design, not as user guides.


1. Export pipeline

World.json (canonical)
   │
   ▼
Export Resolver (per target)
   │  ─ selects assets, generates geometry, bakes navigation
   │
   ▼
Target Bundle
   │  ─ Godot scene tree (.tscn) + TileMaps + NavigationRegion
   │  ─ Unity ScriptableObjects + Prefabs + Addressables
   │  ─ Unreal Landscape + Level instances
   │  ─ Adventure Craft world (gas://world/...)
   │  ─ Foundry VTT module + scene
   │  ─ Bevy scene + plugin
   │  ─ Mobile companion (React Native bundle)
   │
   ▼
Packaging (.zip / .tar / .gas-world / direct publish)

The Export Resolver is deterministic: same World.json + same target options = byte-identical bundle. Re-exports after a small edit only re-pack the changed chunks.


2. Godot

2.1 Output

  • world.tscn — root scene with a TileMap per biome and a NavigationRegion per walkable area.
  • terrain/ — TileSet resources.
  • objects/ — packed scenes for every distinct assetId.
  • scripts/ — NPC behaviour scripts (GDScript).
  • quests/ — Resource files referencing dialogue trees.

2.2 Pipeline

  1. Tile → TileSet atlas (1 PNG per biome, 1024×1024 max).
  2. Object → packed scene (.tscn) with collision shapes derived from objects[].collision.
  3. NPC → scene with GDScript generated from npcs[].schedule + npcs[].goals.
  4. Triggers → Area3D nodes with body_entered signals.
  5. Quests → Resource (res://quests/*.tres) loaded by an autoload QuestManager.

2.3 Bidirectional

  • Godot can re-export a modified scene back to World.json.
  • Unknown Godot nodes are preserved as extras and re-emitted on re-export.

3. Unity

3.1 Output

  • World.asset — top-level ScriptableObject.
  • TerrainData/ — Unity Terrain assets with splatmaps from biome maps.
  • Prefabs/ — one prefab per object, batched.
  • ScriptableObjects/ — NPC, Quest, Encounter definitions.
  • Addressables/ — for streaming chunks in/out.

3.2 Pipeline

  1. Biome map → splatmap texture.
  2. Objects → prefabs (one per asset) instanced via Addressables.
  3. Heightfield → Unity Terrain with biome-driven textures.
  4. NPCs → MonoBehaviour scripts generated from npcs[].
  5. Quests → ScriptableObject + runtime QuestSystem autoload.

3.3 Determinism

Uses Unity's Random seed; the export captures the seed in World.asset so re- exports are reproducible.


4. Unreal

4.1 Output

  • World.umap — root level.
  • Landscape actors with biome-driven materials.
  • Foliage instances for procedural forests.
  • Level instances per region for streaming.
  • Nanite meshes for high-detail objects.

4.2 Pipeline

  1. Heightfield → Landscape actor.
  2. Biome map → Landscape Layer system.
  3. Objects → static mesh instances.
  4. NPCs → ACharacter subclasses generated from npcs[].

4.3 Caveats

  • Nanite requires high-detail GLB inputs. The asset pipeline ships a "Nanite-ready" flag per asset.
  • Level streaming maps regions to World Partition cells.

5. Adventure Craft (native)

Adventure Craft is the playable adventure runtime. Worlds authored in WorldForge load directly as .gas-world files.

5.1 Round-trip

  • WorldForge exports a .gas-world file. Adventure Craft imports it unchanged.
  • Adventure Craft can save back as .gas-world. WorldForge imports the modified file (treating Adventure-Craft-specific extras as opaque).

5.2 What Adventure Craft gets

  • All terrain, objects, NPCs, quests, triggers.
  • Biome-driven default behaviour (jungle slows movement, etc.).
  • Adventure Craft adds its own runtime layer (multiplayer session, voice chat) on top.

6. Foundry VTT

6.1 Output

  • A Foundry VTT module (module.json + scenes + walls + lights).
  • One scene per region.
  • Walls derived from objects[].collision and terrain[].movement.
  • Lights from world.lighting and ambient sources.

6.2 Pipeline

  1. Region → Foundry scene.
  2. Walls → Wall entities.
  3. Lights → AmbientLight + Light from torch / lantern objects.
  4. Tiles → Foundry tile layer.
  5. Tokens → NPC scenes.

6.3 Dynamic lighting

If lighting.dayNightCycle is enabled, the module emits a 光照 hook script that updates the scene's ambient light based on the in-world time. Players see the same day/night cycle in Foundry as in WorldForge.


7. Bevy (via bevy-game-editor)

7.1 Output

  • world.ron — Bevy scene in RON.
  • Bevy plugins for NPC schedules, weather, day/night.

7.2 Pipeline

  1. World.json → Bevy scene with PbrBundle per object.
  2. Heightfield → Bevy Mesh with custom shader for biome splatting.
  3. NPCs → Bevy components (Schedule, Goals, Memory).
  4. Quests → Bevy resources.

The integration with bevy-game-editor makes this a first-class export — worlds authored in WorldForge can be opened, edited, and run inside the Bevy editor.


8. Mobile companion app

8.1 What it is

A lightweight read-only React Native (or Flutter, Phase 5) app that lets players:

  • View the world map with their current position.
  • See active quests.
  • Check inventory + character sheet.
  • Read lore entries (Phase 5).
  • Receive GM broadcasts.

8.2 Data flow

The mobile app talks to the same backend that powers adventure-craft. The world data is not embedded in the app — it is fetched per session.

8.3 Offline mode

A downloaded world bundle (world.gas-world) works offline. The companion app synchronises state changes when reconnected.


9. Asset bake step

For each export target, an asset bake runs:

  1. Resolve every assetId to a target-specific mesh / texture / sound.
  2. Generate collision meshes from objects[].collision + terrain[].movement.
  3. Bake navigation meshes from walkable terrain.
  4. Pack atlas textures (max 4096×4096 per atlas).
  5. Strip assets that the target doesn't use (e.g. GLB-only assets for Godot 2D).

The bake is idempotent — re-running produces the same files.


10. Marketplace publication

A world can be published to the GAS marketplace as a .gas-pack. The marketplace ships:

  • Hero shot.
  • Description.
  • Tags.
  • Licence (CC-BY, CC0, commercial with price).
  • Demo version with locked biomes (preview).

See 10-marketplace-and-packs.md.


11. Validation

Every export runs a target-specific validator that checks:

  • Asset compatibility (e.g. GLB meshes in Unreal must be Nanite-flagged).
  • Script size limits (Godot: 65k char class names).
  • Path length limits (mobile: 256 chars).
  • Licences (every asset must be licensable for the target platform).

Failures are reported as a structured list — the user sees exactly which asset or rule failed and can fix before retrying.


12. Round-trip integrity

After an export, the user can re-import the modified bundle. The result is a World.json that:

  • Preserves all gameplay data (terrain, objects, regions, NPCs, quests).
  • Preserves all biome + theme pack references.
  • Preserves all camera paths.
  • Marks engine-specific extras as extras (round-trippable but not editable in WorldForge).

This is the same World.json, with optional extras. No data is silently lost.

Lore in exports (0.24.0)

When a world has lore (WorldSchema.lore), every target carries it; worlds without lore export byte-identically to before. Source: packages/export/src/lore.ts.

TargetLore output
Bevy / Unity / Unreal / Foundry portable JSONoptional lore key (the GAS lore block, collections sorted by id); payload schemaVersion stays 0.1 (additive)
Godotlore.json sidecar beside world.tscn
Foundry VTTjournal.json + note entryId links (see table above)
Adventure Craftthe world document passes through unchanged, lore included