DEMIENGINEDOCUMENTATION Everything is free
Game systems

In this guide

Importers, manifests, addressable groups, cooking, and portable packs.

Assets & streaming

Typed data assets can be imported with --type DataAsset --content-type terrain_material_set or terrain_palette; surfaces use ordinary Material assets. Import and reimport run the native content parser and derive asset-ID dependencies. Unknown application content types remain ordinary data; strings are not guessed to be asset references. See terrain asset authoring for the editor creation and property controls.

Asset IDs are stable URIs you reference from scenes and scripts. Import records hashes and dependencies; cooking is keyed by content so rebuilds stay fast and deterministic.

Import a source

demi asset import assets/textures/brick.png \
  --id asset://textures/brick

This copies the source into the project and writes a *.asset.json manifest. Supported importers: PNG, JPEG, BMP, TGA, QOI, SVG, GIF, WAV, OGG, MP3, FLAC, glTF/GLB, OBJ, IQM, M3D, MP4/WebM/MOV (media builds), JSON data, plus text (.txt, .yaml, .yml). When two importers could claim a source, pass --importer <id>.

After editing the source file, refresh the manifest:

demi asset reimport assets/textures/brick.asset.json

That recomputes source_hash, dependencies, and generated output. Tools that generate sources under assets/ call demi asset register-generated.

Manifest settings

{
  "format_version": 1,
  "id": "asset://textures/brick",
  "type": "Texture2D",
  "source": "brick.png",
  "settings": {
    "filter": "nearest",
    "wrap": "clamp",
    "mipmaps": false,
    "platform_overrides": {
      "linux": { "compression": "none" },
      "android": { "compression": "astc" }
    }
  }
}
  • Texture filter: nearest|bilinear|trilinear. wrap: repeat|clamp|mirror.
  • Audio: settings.streaming for music and ambience.
  • Fonts: settings.variations (for example {"wght": 700, "opsz": 24}).
  • Data: settings.schema, content_type, tags — see Game data.
  • platform_overrides lets one manifest differ per platform without duplicate assets.

Terrain assets

Terrain sources use *.terrain.json, type Terrain and importer terrain_heightfield. Scenes place them through Terrain3D.asset. Select a placement to sculpt or paint in the scene Viewport; its Terrain Graph contains generation settings and modules. Apply changes to the shared asset without embedding recipes in the scene. The editor and build tools prepare the generated data; shipped games load the cooked payload. See Terrain assets and editing for creation, graph editing and shipping.

Atlases

TextureAtlas2D packs sprites from a units descriptor: page_width, page_height, padding, bleed, and sprites[] entries with id, source, pivot, border, and animation_tag. FontAtlas2D rasterizes glyphs with pixel_height, page_size, padding, glyph_ranges, and fallbacks.

Startup preload and addressable groups

The project assets array is startup preload only — anything else loads on demand or with its scene. Group related assets for batched streaming:

{
  "format_version": 1,
  "id": "asset-group://level_one",
  "roots": ["asset://levels/one", "scene://game/level_one"],
  "budget": {
    "resident_mb": 192,
    "decoded_mb": 384,
    "upload_ms_per_frame": 3
  }
}

budget records resident and decoded memory limits and the per-frame upload budget. Measure the loaded group's actual memory use with Assets.memory_report() when tuning these values.

Loading from Lua

local Assets = require("demi.assets")
local Audio = require("demi.audio")
local Game = {}

local request, err = Assets.load("asset://music/theme")
if not request or request == 0 then error(err) end
local started = false

function Game:on_update()
    if Assets.is_ready(request) then
        if not started then
            Audio.play("asset://music/theme", { bus = "music", loop = true })
            started = true
        end
    else
        local p = Assets.progress(request)
        -- p.stage names the stage; p.fraction is 0.0 … 1.0
    end
end

function Game:on_stop_music()
    Assets.cancel(request)                  -- only matters while pending
    Assets.unload("asset://music/theme")    -- release this owner
end

return Game
CallReturns
Assets.load(uri)Request ID and error string. Keep the ID to poll or cancel this load.
Assets.is_ready(request)Boolean, true when the request reached ready.
Assets.progress(request)Table with stage, fraction (0…1), asset counts, byte totals, and error. Stages: resolve, read, decode, upload, ready, failed, cancelled.
Assets.text(uri)Cached contents of a loaded text asset, or nil, plus an error string.
Assets.memory_report()Current pending, decoded, and resident bytes plus per-asset entries.

Scene transitions build an implicit group from the scene:// root and activate atomically at a frame boundary. A failed reload keeps the previous resident version.

For other loaded resources, Assets.text(asset_id) returns cached text or nil plus an error string; Assets.reload(asset_id) picks up a changed source; Assets.memory_report() reports pending, decoded, and resident bytes and per-asset owners.

Cooking

demi cook --platform linux

Output is generated/cooked/<platform> plus cook.manifest.json listing every included path and hash. Cache keys include importer identity and version, normalized settings, source hashes, platform, and package provenance — so a rebuild only redoes what changed.

Portable asset packs

demi asset export \
  --output brick_pack.demipack --asset asset://textures/brick

demi asset import-package brick_pack.demipack
 

.demipack is a deterministic container: versioned JSON index plus sorted file data with IDs, manifest paths, sizes, and checksums. Import rejects absolute paths, .., checksum failures, and implicit overwrites.

Collider assets

demi asset collider assets/models/crate.glb.asset.json \
  --id asset://colliders/crate

Generates a Collider3D asset from a model. Triangle-mesh results are static-only; convex or compound collider assets can support moving bodies. See Colliders for authored collider sources and attachment.

Performance budgets

demi asset budget games/my_game/demi.project.json --platform android

Reports usage against project performance_budgets: frame time, draw calls, resident assets, visible instances, unique meshes, triangles, texture memory, lights, shadow lights, and transparent draws.