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)
| Target | Status | Depth | Notes |
|---|---|---|---|
.gas-world JSON | ✅ SHIPPED | Full round-trip | Canonical 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 primitive | Node2D 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-trip | exportAdventureCraft + 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-22 | exportUnity(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-22 | exportUnreal(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-22 | exportFoundry(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-22 | exportBevy(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 aTileMapper biome and aNavigationRegionper walkable area.terrain/— TileSet resources.objects/— packed scenes for every distinctassetId.scripts/— NPC behaviour scripts (GDScript).quests/—Resourcefiles referencing dialogue trees.
2.2 Pipeline
- Tile → TileSet atlas (1 PNG per biome, 1024×1024 max).
- Object → packed scene (
.tscn) with collision shapes derived fromobjects[].collision. - NPC → scene with GDScript generated from
npcs[].schedule+npcs[].goals. - Triggers →
Area3Dnodes withbody_enteredsignals. - Quests →
Resource(res://quests/*.tres) loaded by an autoloadQuestManager.
2.3 Bidirectional
- Godot can re-export a modified scene back to
World.json. - Unknown Godot nodes are preserved as
extrasand 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
- Biome map → splatmap texture.
- Objects → prefabs (one per asset) instanced via Addressables.
- Heightfield → Unity Terrain with biome-driven textures.
- NPCs → MonoBehaviour scripts generated from
npcs[]. - Quests → ScriptableObject + runtime
QuestSystemautoload.
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.Landscapeactors with biome-driven materials.Foliageinstances for procedural forests.Level instancesper region for streaming.Nanitemeshes for high-detail objects.
4.2 Pipeline
- Heightfield → Landscape actor.
- Biome map → Landscape Layer system.
- Objects → static mesh instances.
- NPCs →
ACharactersubclasses generated fromnpcs[].
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 Partitioncells.
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-worldfile. 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[].collisionandterrain[].movement. - Lights from
world.lightingand ambient sources.
6.2 Pipeline
- Region → Foundry scene.
- Walls →
Wallentities. - Lights →
AmbientLight+Lightfrom torch / lantern objects. - Tiles → Foundry tile layer.
- 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
World.json→ Bevy scene withPbrBundleper object.- Heightfield → Bevy
Meshwith custom shader for biome splatting. - NPCs → Bevy components (
Schedule,Goals,Memory). - 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:
- Resolve every
assetIdto a target-specific mesh / texture / sound. - Generate collision meshes from
objects[].collision+terrain[].movement. - Bake navigation meshes from walkable terrain.
- Pack atlas textures (max 4096×4096 per atlas).
- 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.
| Target | Lore output |
|---|---|
| Bevy / Unity / Unreal / Foundry portable JSON | optional lore key (the GAS lore block, collections sorted by id); payload schemaVersion stays 0.1 (additive) |
| Godot | lore.json sidecar beside world.tscn |
| Foundry VTT | journal.json + note entryId links (see table above) |
| Adventure Craft | the world document passes through unchanged, lore included |