DEMIENGINEDOCUMENTATION Everything is free
Start here

In this guide

Projects, scenes, entities, components, prefabs, assets, and packages.

Core concepts

DemiEngine games are readable, versioned documents. The editor and the CLI read the same source; nothing required to ship a game lives in editor-only state.

Concept map

ConceptPurposeIdentity
ProjectGame-wide settings, scene list, input, physics layers, build metadatademi.project.json
SceneA set of entities loaded togetherscene://game/main
EntityAn object with a stable ID and componentsplayer, wall_north
ComponentData describing one capability on an entityTransform3D, MeshRenderer, Sprite
PrefabReusable entity composition with per-instance overridesprefab://doorway
HUD / UI prefabScreen-space interface tree / reusable UI subtree*.hud.json, ui-prefab://button
AssetImported resource referenced by stable identityasset://textures/brick
PackageInstallable Lua modules or assets shared across projectsdemi.gameplay.health
ScriptLua gameplay attached to an entityscript://scripts/player.lua

Stable identity and URIs

Every durable document keeps format_version. References use URI schemes, never array positions or editor-only handles:

  • scene://namespace/main → scenes/main.scene.json
  • prefab://characters/player → prefabs/characters/player.prefab.json
  • ui-prefab://controls/menu_button → ui/controls/menu_button.ui.prefab.json
  • asset://textures/brick → assets/textures/brick.asset.json
  • asset-group://level_one → assets/level_one.asset-group.json
  • script://scripts/player.lua → scripts/player.lua

Project scene entries may omit path when the conventional path can be inferred from the scene ID. Explicit paths remain valid.

Entities and hierarchy

Entities carry a stable document-wide ID, optional name/tags/layer, and a components object. Prefer children arrays for visually meaningful local hierarchies:

{
  "id": "house",
  "components": { "Transform3D": { "position": [0, 0, 0] } },
  "children": [
    { "id": "roof", "components": { "Transform3D": { "position": [0, 2, 0] } } }
  ]
}

IDs stay document-wide; nesting is not an ID namespace. Keep explicit transform parent for cross-prefab or cross-scene relationships that cannot be nested in the authored document.

Hierarchy rule

Transform parents must share a dimensional domain: Transform2D, Transform3D, or IsoTransform. Mixed domains and conflicting explicit parents are validation errors. Maximum nesting depth is 128.

Components, not frameworks

A component is authored JSON data for one capability on an entity. Examples: Sprite, SpriteAnimator2D, Tilemap2D, Camera2D, Rigidbody2D, MeshRenderer, AnimationPlayer3D, CharacterController3D, Fracture3D, AudioSource, LuaScript.

Fields you omit use the component’s defaults, so newly authored JSON stays short. Write only the values that differ from the default. Existing explicit values are preserved as-is.

Assets contain resources; entities use them. A model asset does not itself have health, collision, or game logic. Add those components or scripts to the entity that renders the model, then save the composition as a prefab.

Lua gameplay

Gameplay rules live in Lua. Import the services you need and call them through the returned table:

local Input = require("demi.input")
local Transform3D = require("demi.transform3d")

local x, y = Input.vector("move")          -- -1 … 1 per axis
local px, py, pz = Transform3D.get_position("player")

Optional gameplay packages install Lua modules under dotted namespaces such as demi.gameplay.health or demi.network.session.

See Lua scripting and the Lua API reference.

Source, generated, and writable data

  • Source — scenes, prefabs, scripts, asset manifests, data, project files. You edit these.
  • Generated — cook output, imported generated sources, fracture geometry, installed packages under .demi/. Never hand-edit; never commit build outputs.
  • Writable — game saves and caches use platform user-data/cache directories, never the application or cooked source directory.

Determinism

Simulation uses a project-fixed timestep (default 1/60) with a capped number of fixed steps per frame. Randomness is seeded from the project. Physics contacts are dispatched in a stable order. Input can be recorded and replayed. These rules make runs, replays, and E2E tests comparable.

Where to continue