DEMIENGINEDOCUMENTATION Everything is free
Project & file formats · Start here

Manifest fields, importers, settings, and groups.

Asset manifests

An asset manifest is a small JSON file that gives one game resource a stable identity and records how it should be imported. Textures, fonts, sounds, models, and data files are all referenced the same way — by an asset:// URI — and the manifest is what stands behind that name. This page explains what a manifest contains and how its settings shape each kind of asset.

What a manifest is

Two jobs, one file:

  • Identity — the id is the name the rest of the game uses. Scene components, HUD nodes, and scripts say asset://textures/brick; nobody embeds a file path. If you move the source image on disk, the name does not change.
  • Import settings — how the source file is turned into a runtime resource: filtering, wrapping, compression, quality, font axes, and so on. These are authored decisions, not guesses made at load time.

Manifest files are named *.asset.json and live under the project's assets/ tree. Every manifest starts with format_version.

URI convention: asset://textures/brick points at assets/textures/brick.asset.json. The engine references assets by URI only — see demi.project.json for how project-level references work.

A minimal texture manifest

{
  "format_version": 1,
  "id": "asset://textures/brick",
  "type": "Texture2D",
  "source": "assets/textures/brick.png",
  "settings": {
    "filter": "nearest",
    "wrap": "repeat"
  }
}

Field by field:

FieldMeaning
format_versionAlways required. Documents without it are rejected.
idThe asset URI. asset://textures/brick maps to this file at assets/textures/brick.asset.json.
typeWhat kind of resource this is (here Texture2D). The type decides which importer runs and which settings apply.
sourcePath to the original file being imported (here a PNG). Relative paths are resolved inside the project.
settingsType-specific import options. For textures: filter chooses the sampling sharpness (nearest for crisp pixels, bilinear, trilinear for smooth scaling), wrap chooses what happens at the edges (repeat, clamp, mirror).

That is the whole contract: name it, type it, point at the file, describe how to treat it.

Asset types

type selects one of these resource kinds:

TypeHolds
Texture2DA 2D image.
TextureAtlas2DSeveral sprites packed into one image.
SpriteMetadata2DSlicing information for sprites inside a texture.
Font2DA font face.
FontAtlas2DRasterized glyphs ready to draw.
Model3DA 3D model, with optional animation clips.
Collider3DA 3D collision shape.
TerrainAn editable terrain source, cooked into prepared heightfield, collision-input and placement data. See Terrain assets.
AudioClipA sound or music file.
VideoClipA video file.
DataAssetStructured game data (tables, configs) with a content type and tags.
DataSchemaA schema describing the shape of data.
NetworkContractThe message/component contract for networked play.
MaterialSurface appearance settings.
ShaderA shader program.
RenderTargetA GPU surface drawn into at run time.
Tilemap2DA tiled 2D level layout.
TextA plain text document (.txt, .yaml, .yml).
Icon2DAn application icon source.
SvgTexture2DA vector image rasterized to a texture.
GifAnimation2DAn animated GIF.
ImageAnimation2DAn image sequence animation.

Change tracking: source_hash and dependencies

"source_hash": "fnv1a64:8c31a9d2e01b44f7",
"dependencies": [
  "asset://textures/hero_mask"
]
  • source_hash is a fingerprint of the source file, written as fnv1a64: plus 16 hex digits (no 0x prefix). It tracks changes: when the file on disk differs from the recorded hash, the asset is re-imported. You do not edit this value by hand; it is recorded for you.
  • dependencies lists other assets this one needs. If a dependency is re-imported, this asset is updated too, so nothing stale is served.

Together they answer one user-facing question: "has anything this asset depends on changed since last import?" If yes, the next build or cook refreshes it automatically.

Settings by kind

The settings object changes meaning with type. Common fields:

Textures

"settings": {
  "filter": "bilinear",
  "wrap": "clamp",
  "mipmaps": true,
  "compression": "quality",
  "quality": 90
}
  • filter — nearest, bilinear, or trilinear. Pixel art usually wants nearest.
  • wrap — repeat, clamp, or mirror at the edges.
  • mipmaps — build smaller copies for distant/scaled rendering.
  • compression / quality — how much the file is squeezed in exchange for size. quality is an integer from 0 to 100.

Audio

"settings": {
  "streaming": true
}
  • streaming — play long files from disk in chunks instead of loading them entirely into memory. Good for music; short effects usually stay fully loaded.

Fonts

"settings": {
  "glyph_ranges": ["U+0020-U+007E"],
  "variations": { "wght": 700, "opsz": 24 }
}
  • glyph_ranges — Unicode ranges to rasterize, written like "U+0020-U+007E". Only include what your text needs; every extra glyph costs atlas space.
  • variations — variable-font axes as 4-character OpenType tags mapped to numbers (for example wght for weight, opsz for optical size).

Data assets

"settings": {
  "schema": "asset://data/loot_schema",
  "content_type": "application/json",
  "tags": ["loot", "economy"]
}
  • schema — an optional asset:// reference to a DataSchema the content is checked against.
  • content_type — what kind of data the file holds.
  • tags — free-form labels for querying and tooling.

Models

"settings": {
  "animations": {
    "clips": [
      { "name": "Idle", "skeleton": "humanoid" },
      { "name": "Run",  "skeleton": "humanoid" }
    ]
  }
}
  • animations.clips — an array of clip descriptors. Each entry names an animation clip and the skeleton it plays on, so gameplay can request Idle or Run by name.

Platform overrides

Some resources must look or load differently per platform:

"settings": {
  "filter": "bilinear",
  "platform_overrides": {
    "linux": { "compression": "none" },
    "linux_server": { "quality": 50 },
    "android": { "compression": "size", "mipmaps": true }
  }
}
  • platform_overrides keys are linux, linux_server, and android.
  • Each entry lists setting fields that replace the base values when cooking for that platform. Android might trade quality for size; a headless server build might drop expensive options.
  • Fields you do not override keep their top-level settings values.

Importer metadata, license, and attribution

"importer": "image",
"importer_version": 1,
"license": "CC0-1.0",
"attribution": "Brick texture by A. Artist",
"generated_output": "generated/assets/textures/brick"
  • importer / importer_version — which import path handled this asset and its revision. Recorded automatically when the asset is imported.
  • license — the license of the source file. Required for anything you did not make yourself.
  • attribution — credit text for the author. Ship it with the game when the license asks for it.
  • generated_output — where the imported result is written during a build. Generated files are build output, not authored source; do not edit them.

Asset groups

Assets are loaded one by one on purpose — a texture only loads when something asks for it. When you do want a batch (everything a level needs, loaded together), you write an asset group in a separate *.asset-group.json document:

{
  "format_version": 1,
  "id": "asset-group://level_one",
  "roots": [
    "asset://textures/brick",
    "scene://game/level_one"
  ],
  "budget": {
    "resident_mb": 128,
    "upload_ms_per_frame": 2,
    "decoded_mb": 256
  }
}
  • id is an asset-group:// URI: asset-group://level_one maps to assets/level_one.asset-group.json.
  • roots lists what the group covers — individual asset:// entries and/or whole scene:// entries.
  • budget states the limits you intend to stay under: resident_mb (memory held after load), upload_ms_per_frame (how much upload work per frame), decoded_mb (optional decoded-size ceiling).

Groups do not change what individual assets mean; they only batch loading and unloading. The project's assets array is startup preload only. Full workflow: Asset groups & streaming, and budgets on Performance budgets.

Where manifests are used