Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit61a33237e0

README.md

asset_create

asset.create — the single, generic "instance a new asset of an existing type" API. The same entry point scripts and agents use; there is deliberately no tool wrapper, because agents author in Luau and call asset.create(...) directly.

local inst = asset.create("material", "my_metal", { base_color = { 0.8, 0.7, 0.2 } })
-- → AssetRef: inst.path == "/zero/source/my_metal.material", inst.guid, plus the
--   material type's ref methods.

asset.create makes a new instance of an already-registered type by running that type's onCreate(name, opts) behaviour hook (declared in its behavior.luau) and writing the produced files to /zero/source/<name>.<typeName>/ — the one authored location, in every mode.

While play runs, the play-mode write lock takes that write onto the play shadow: live in the session, listed by vfs.playShadowPaths(), and promoted or discarded on a guarded play-exit. The asset created in play therefore carries the same identity, path and require spelling it has in edit, and the session decides whether it stays.

A create whose output the world reproduces on every load — one made from a component or a scene entrypoint — writes to the copy-on-write runtime store at /zero/runtime/assets/<identity>.<typeName>/ instead, so the code that rebuilds it each load is its only source and the saved manifest never carries a second copy.

Placement

Four opts keys are consumed by the framework before the type's onCreate hook runs, and steer where the instance lands:

KeyEffect
folderA relative subfolder under the source root: /zero/source/<folder>/<name>.<typeName>/. Groups a generator's output instead of accumulating it at the source root.
intoA resolved container ref (.toolbox / .package) to author INSIDE — lands at <container>/<name>.<typeName>/ and registers as a member. Edit-mode only.
destAn absolute destination path, owned by the caller (an importer building a <name>.bundle/).
overwriteRe-author an existing destination in place, keeping its .meta guid so every reference stays valid.

The name is always the asset's bare identity — the path goes in folder:

local rock = asset.create("mesh", "rock", { positions = p, indices = i, folder = "terrain/props" })
-- → rock.path == "/zero/source/terrain/props/rock.mesh"

dest and into both take precedence over folder. folder decides the asset's identity, so it applies in every context: the runtime store is flat and spells that identity in one folder name.

-- the same call from a component's awake()
-- → rock.path     == "/zero/runtime/assets/terrain.props.rock.mesh"
-- → rock.identity == "terrain.props.rock", as it is from an execute

Types without an onCreate hook fall back to cloning their verbatim template/ skeleton to the same destination, so create works for every type. Returns the created asset's AssetRef (.path / .guid plus the type's ref methods — the same interned instance asset.resolve returns) on success and raises (via error) on bad arguments or a failing onCreate.

Installed onto the FFI asset namespace by the prelude (M.installInto(asset)). See docs/specs/runtime-asset-copying.md.