Export Assets With The CLI
This tutorial shows how to export your own assets with the untoldengine CLI
and where to place the resulting files inside a generated Xcode project.
Use the CLI when you want a repeatable terminal workflow. Use the Blender add-on when you want a visual Blender export workflow.
Project Asset Layout
Generated projects bundle runtime assets from:
Sources/<ProjectName>/GameData/
Models/
StreamModels/
Animations/
Gaussians/
Textures/
HDR/
Shaders/
The common runtime paths are:
| Asset Type | Recommended Location |
|---|---|
| Single models | GameData/Models/<AssetName>/<AssetName>.untold |
| Animation clips | GameData/Animations/<ClipName>/<ClipName>.untold |
| Streamed scenes | GameData/StreamModels/<SceneName>/<SceneName>.json plus tile_exports/ |
| Shared textures | beside the exported .untold asset or under GameData/Textures/ |
| HDR environments | GameData/HDR/<Environment>.hdr |
The engine resolves filenames through the project's configured GameData
directory, so examples usually pass only the filename stem:
Install Export Dependencies
Install the CLI first:
If you plan to optimize textures or geometry, bootstrap the external tools once:
This installs the pinned astcenc texture compressor and required Python
packages used by optimization workflows.
Export A Single Model
From any directory:
untoldengine export \
--input /path/to/robot.usdz \
--output ~/Projects/MyGame/Sources/MyGame/GameData/Models/robot/robot.untold \
--convert-orientation
.blend input works too:
untoldengine export \
--input /path/to/robot.blend \
--output ~/Projects/MyGame/Sources/MyGame/GameData/Models/robot/robot.untold \
--convert-orientation
Load it in GameScene.swift:
let robot = createEntity()
setEntityName(entityId: robot, name: "Robot")
setEntityMeshAsync(entityId: robot, filename: "robot", withExtension: "untold") { success in
guard success else {
setSceneReady(false)
return
}
translateTo(entityId: robot, position: .zero)
setSceneReady(true)
}
Add Validation
Use --validate while building an asset pipeline:
untoldengine export \
--input /path/to/robot.usdz \
--output ~/Projects/MyGame/Sources/MyGame/GameData/Models/robot/robot.untold \
--convert-orientation \
--validate
This writes a sidecar validation JSON file next to the exported asset. It is not required at runtime, but it is useful for checking mesh counts, vertex counts, and export results.
Optimize The Export
Run bootstrap once:
Then export with optimization:
untoldengine export \
--input /path/to/robot.usdz \
--output ~/Projects/MyGame/Sources/MyGame/GameData/Models/robot/robot.untold \
--convert-orientation \
--optimize
--optimize compresses geometry and, when textures are present, bakes and
patches textures to .utex.
Use --bake-materials when Blender materials use node graphs the runtime cannot
evaluate directly:
untoldengine export \
--input /path/to/lamp.blend \
--output ~/Projects/MyGame/Sources/MyGame/GameData/Models/lamp/lamp.untold \
--convert-orientation \
--bake-materials
Export Animation Clips
Export animation-only .untold files with --animation:
untoldengine export \
--input /path/to/running.usdz \
--output ~/Projects/MyGame/Sources/MyGame/GameData/Animations/running/running.untold \
--convert-orientation \
--animation
Register clips on the loaded character:
setEntityAnimations(entityId: character, filename: "idle", withExtension: "untold", name: "idle")
setEntityAnimations(entityId: character, filename: "running", withExtension: "untold", name: "running")
changeAnimation(entityId: character, name: "idle")
Keep clip names simple and consistent. The name argument is the runtime handle
used by changeAnimation(...).
Export Color Management
If the scene should match Blender's View Transform, Look, Exposure, and Gamma, export a baked color LUT:
untoldengine export \
--input /path/to/office.blend \
--output ~/Projects/MyGame/Sources/MyGame/GameData/Models/office/office.untold \
--convert-orientation \
--bake-color-management
Load scene-authored data after the mesh:
loadSceneAuthored(filename: "office", withExtension: "untold") { success in
// Baked color management and authored scene data are registered.
}
setEntityMeshAsync(...) does not load the baked LUT by itself.
Export A Streamed Scene
For large scenes, export a manifest and tile payloads into GameData/StreamModels:
untoldengine export-tiles \
--input /path/to/city.usdz \
--output-dir ~/Projects/MyGame/Sources/MyGame/GameData/StreamModels/City/tile_exports \
--tile-size-x 25 \
--tile-size-z 25 \
--generate-hlod \
--generate-lod \
--optimize
Expected layout:
Load the manifest:
let sceneRoot = createEntity()
setEntityName(entityId: sceneRoot, name: "City")
setEntityStreamScene(entityId: sceneRoot, manifest: "City", withExtension: "json") { success in
setSceneReady(success)
}
For remote hosting, upload the manifest folder and pass a URL:
Choose Partitioning
Use a uniform grid for simple outdoor scenes:
untoldengine export-tiles \
--input /path/to/site.usdz \
--output-dir ~/Projects/MyGame/Sources/MyGame/GameData/StreamModels/Site/tile_exports \
--tile-size-x 25 \
--tile-size-z 25
Use quadtree for multi-floor buildings:
untoldengine export-tiles \
--input /path/to/building.usdz \
--output-dir ~/Projects/MyGame/Sources/MyGame/GameData/StreamModels/Building/tile_exports \
--quadtree \
--scene-profile indoor
Use KD-tree when geometry is clustered unevenly:
untoldengine export-tiles \
--input /path/to/building.usdz \
--output-dir ~/Projects/MyGame/Sources/MyGame/GameData/StreamModels/Building/tile_exports \
--kdtree \
--scene-profile indoor
Common Mistakes
| Problem | Fix |
|---|---|
| Asset does not load | Confirm the .untold file is under Sources/<ProjectName>/GameData/Models/<name>/. |
| Animation does not play | Confirm the clip was exported with --animation and registered with setEntityAnimations(...). |
| Blender look does not match | Export with --bake-color-management and call loadSceneAuthored(...). |
| Tiled scene does not stream | Confirm the manifest is under GameData/StreamModels/<SceneName>/ and tile paths are relative to it. |
| Optimized export fails | Run untoldengine bootstrap, then rerun the export. |