Log inGet started

Importer (asset type)

An importer is a Luau function that converts a source file (GLB, PNG, CSV, custom binary) into one or more derived assets registered in the engine. Importers extend the engine's file-format knowledge…

When to use one

  • You're bringing a new file format into the engine and want to derive engine-native assets from it (meshes, textures, animations, data tables).
  • You want one VFS write to fan out into multiple derived assets (e.g. a GLB write derives mesh, texture, and animation assets).
  • You want format ingestion to be idempotent + hot-reloadable — importers re-run on source-file changes.

If you only need to consume an existing engine asset type, you don't need an importer; just load via asset.load. If you're building an authoring tool that emits assets, that's a .tool, not an importer.

Where it lives

  • Source: /zero/source/.../<name>.importer/
  • Identity: <name> (the .importer suffix strips).
  • Folder shape:
    • init.luau (or init.lua) — exports canImport and import. Required.
    • README.md — instance documentation. Required.

How to create one

asset.create("importer", "<name>")
-- Creates: /zero/source/importers/<name>.importer/
--   init.luau   (canImport / import stubs)
--   README.md   (instance README template)

How it operates

  1. Registration. Writing init.luau into a .importer/ folder indexes the importer with the importer registry.
  2. Dispatch. When a file is written to VFS, the engine asks every registered importer canImport(path, bytes) (cheap predicate). The first importer that accepts dispatches to its import function.
  3. Derivation. import(path, bytes) returns a list of { path, kind } pairs naming the assets to derive. The engine instantiates each derived asset against its registered category.
  4. Idempotency. import MUST be deterministic — importing the same source bytes twice produces identical derived assets. The importer pipeline uses content-hashing to short-circuit re-imports when bytes haven't changed.
  5. Hot reload. Editing the importer reloads it; subsequent writes use the new logic. Already-imported assets stay imported with the old derivation until their source is re-written — any write of the source path re-dispatches the importers (that is the only trigger; there is no separate "run" call). Writing the source is therefore both the first import and the way to force a re-import.

Discovery

  • asset.list("importer") — every registered importer.
  • asset.inspect("<name>") — claimed extensions, derivation conventions, source, this type README.
  • cat /zero/source/<name>.importer — same summary.
  • /zero/importers/index (VFS) — the importer registry.

Authoring conventions

  • Keep canImport cheap — it's called for every VFS write. Match on extension or a quick header probe; defer real parsing to import.
  • Name derived assets predictably (e.g. imported/<source-stem>/<asset-name>). Predictable paths let callers reference derived assets directly.
  • Make import pure relative to its inputs. Don't read mutable globals or side-channel state.
  • Log derivations via print / the script log so authors can see what got produced from each source.

Common pitfalls

  • Expensive canImport. It runs on every VFS write; an expensive predicate slows down the entire authoring loop.
  • Non-idempotent import. Re-importing produces different output → content hashing falsely caches stale results. Use only deterministic transforms.
  • Conflicting importers. Two importers claiming the same extension causes ambiguous dispatch. First-registered wins, but this is fragile — coordinate ownership of file extensions.
  • Derived-asset suffixes. Make sure derived paths end in the right .<category> suffix; otherwise they won't register as recognized assets.
  • .module — for plain ingestion helpers that don't need the importer dispatch path.
  • .tool — for one-off conversions an agent invokes manually.
  • .service — if your importer needs persistent state (e.g. a cache); the service owns it, the importer reads from it.
  • asset-type
  • reference