Log inGet started

asset

The asset namespace — the engine's Luau API reference for asset.

The asset namespace — 33 functions.

asset/create

asset.create(typeName: string, name: string, opts: table?) -> table

[Library] Instance a new asset of an existing registered type: runs that type's onCreate(name, opts) behavior hook (or clones its template/ skeleton when it has none) and writes the produced files to the mode-aware destination (/zero/source/<name>.<type>/ in edit, the copy-on-write /zero/runtime/assets/<type>/<name>/ store in play). Returns the instance descriptor { typeName, name, dest, mode, files }; raises on bad arguments or a failing onCreate.

globals/asset/add_tag

globals/asset/add_tag(ref: RefArg, tag: string)

Add a tag to the asset's .metadata.tags. Idempotent. Creates the sidecar and the tags array if missing.

globals/asset/categories

globals/asset/categories() -> { string }

List every asset category the engine currently recognises. Use to discover valid type argument values for the rest of asset.*.

globals/asset/containerize

globals/asset/containerize(ref: RefArg, outputName: string) -> string

Copy an asset and every dependency it transitively references into /source/<outputName>.bundle/ with fresh guids. Returns a promise — await(...) it before treating the bundle as ready.

globals/asset/containing

globals/asset/containing(path: string) -> AssetRef?

Walk path's ancestors and return an AssetRef handle for the OUTERMOST category-folder containing it (e.g. main.scene for "/source/scenes/main.scene/scene.json"). Returns nil for paths outside any registered asset type.

globals/asset/create

globals/asset/create(typeName: string, name: string, opts: { [string]: any }?) -> AssetRef

Instance a new asset of an existing type. Runs the type's behavior.luau onCreate(name, opts) hook to produce the asset's files, then writes them under /source/<name>.<type>/. This is the single generic asset-creation API. Refuses to clobber an existing edit-mode asset unless opts.overwrite = true, which re-authors it in place and keeps the existing guid (only the checksum changes). Pairs with asset.exists for content generators that re-run over the same names.

globals/asset/deps

globals/asset/deps(ref: RefArg, type: string?) -> DepsResult

Return the asset's outbound dependency graph — every other asset recorded as a content dependency of it.

globals/asset/describe

globals/asset/describe(typeName: string) -> DescribeResult

The creation contract for an asset type: the parameters its onCreate(name, opts) hook accepts, as data. kind is "schema" (typed contract), "legacy" (untyped opts — anything passes), "none" (template scaffold — takes no opts), or "error" (the type's schema failed to parse; error says why). contract is the human-readable rendering validation errors print.

globals/asset/exists

globals/asset/exists(name: string, typeName: string) -> boolean

Whether an asset named name of type typeName exists in the current mode's store (/source in edit, the runtime fork in play). A plain existence probe — it does NOT resolve a handle or pin a content dependency, so it is safe to call with a COMPUTED name (unlike asset.resolve, whose handle would become a static-pinned dependency).

globals/asset/get_field

globals/asset/get_field(ref: RefArg, key: string) -> any

Read one top-level field from the asset's .metadata.

globals/asset/guid

globals/asset/guid(ref: RefArg, type: string?) -> string

Return the guid for an asset.

globals/asset/has_field

globals/asset/has_field(ref: RefArg, key: string) -> boolean

True when the asset's .metadata carries the named field.

globals/asset/has_tag

globals/asset/has_tag(ref: RefArg, tag: string) -> boolean

True when the asset's .metadata.tags contains tag.

globals/asset/identity

globals/asset/identity(ref: RefArg, type: string?) -> string

Return the canonical identity for an asset.

globals/asset/import

globals/asset/import(path: string) -> string?

Import a raw source file NOW and return the produced asset path (a .bundle for a model, .texture for an image, .audio for a sound, …), or nil if no importer claims it. This is the deterministic, on-demand counterpart to the engine's automatic import-on-write: it runs in the calling task and returns only when the import is complete. Pair it with a quiet write — vfs.write(path, bytes, { quiet = true }) lands the raw bytes without firing the automatic importer, then asset.import(path) imports them under your control, so you can act on the result instead of polling for the import to appear.

globals/asset/inspect

globals/asset/inspect(ref: RefArg, type: string?) -> InspectRecord

Inspect an asset. Resolves ref, builds the common envelope every asset shares (identity, name, guid, source, typeName, typeDefinitionPath, scope, origin, description, tags), then dispatches to the resolved type's ref.inspect(self) (declared on its behavior.luau) for the type-specific detail. A type with no inspect hook leaves detail nil — the envelope alone. A hook that raises leaves detail nil and sets warning with the error text; asset.inspect itself never raises for a resolved ref.

globals/asset/list

globals/asset/list(type_or_opts: (AssetCategory | ListOpts)?, scope: string?, opts: ListOpts?) -> { AssetRef }

List registered assets as resolved AssetRef handles, optionally filtered by type, VFS path, scope, and .metadata fields. Each entry is the same envelope asset.resolve returns (__ref / type / name / guid / identity / path), so it can be passed anywhere an AssetRef is accepted. Accepts the table-only call form asset.list({ type = ..., path = ..., scope = ..., fields = ... }); type takes the same values asset.categories() lists, and path narrows to one VFS subtree (the folder and everything under it). The first positional argument is a path when it starts with /, a type otherwise. A key outside type / path / scope / fields raises. category is the older spelling of type; a table setting both raises. A static (literal) type or path makes the enumeration part of the calling file's content dependencies when it is saved — the set travels with published content, so consumers get at-least the authoring world's assets.

globals/asset/list_field_values

globals/asset/list_field_values(key: string) -> { any }

Distinct values seen for the named field across every asset's .metadata.

globals/asset/list_fields

globals/asset/list_fields() -> { string }

Distinct top-level field keys observed across every asset's .metadata. Useful for tooling discovering custom keys in use.

globals/asset/meta

globals/asset/meta(ref: RefArg, type: string?) -> AssetMeta

Read the asset's engine-owned identity record (guid / checksum). Distinct from .metadata (agent-editable); for that use asset.metadata.

globals/asset/metadata

globals/asset/metadata(ref: RefArg, type: string?) -> AssetMeta

Read the asset's agent-editable .metadata sidecar as a Lua table. Missing sidecar returns {}. Distinct from asset.meta (engine-owned).

globals/asset/preview

globals/asset/preview(ref: RefArg, opts: { [string]: any }?, type: string?) -> { [string]: any }

Render a preview of an asset. Resolves the ref and dispatches to its type's preview ref-method when present; otherwise returns the { available = false } sentinel ("no preview available for this type").

globals/asset/ref

globals/asset/ref(ref: RefArg, type: string?) -> AssetRef?

Build a reference handle for an asset — the canonical ref envelope constructor. Identical shape to asset.resolve; preferred name for the author-side use case (embedding refs in YAML / JSON / Luau output).

globals/asset/remove_field

globals/asset/remove_field(ref: RefArg, key: string)

Remove one top-level field from the asset's .metadata. No-op when the field isn't present.

globals/asset/remove_tag

globals/asset/remove_tag(ref: RefArg, tag: string)

Remove a tag from the asset's .metadata.tags. No-op when the tag isn't present.

globals/asset/resolve

globals/asset/resolve(ref: RefArg, type: string?) -> AssetRef?

Find an asset. The returned handle carries every name form the asset has (guid, identity, path, type) so downstream code can read any one of them without calling resolve again. Raises when ref resolves to no asset — or, with a type, to no asset of that type — and when a bare no-type name is ambiguous across categories (it never silently prefers one category). For a presence check that never raises, use asset.exists(name, type); to handle a possible miss inline, wrap the call in pcall.

globals/asset/set_field

globals/asset/set_field(ref: RefArg, key: string, value: any)

Set one field in the asset's .metadata, creating the sidecar if missing. Sibling fields are preserved. When the new value AND the existing value are both maps (objects), the new value DEEP-MERGES into the existing one, so writing one sub-key never drops the others — set_field(ref, "settings", { keepCpu = true }) keeps every other setting. Arrays and scalars replace. Clear a whole field with asset.remove_field; replace the entire sidecar with asset.set_metadata.

globals/asset/set_metadata

globals/asset/set_metadata(ref: RefArg, data: AssetMeta)

Replace the asset's .metadata sidecar with the given table. Pass an empty table to clear all fields.

globals/asset/source

globals/asset/source(ref: RefArg, type: string?) -> string

Return the VFS source path for an asset.

globals/asset/tags

globals/asset/tags(ref: RefArg) -> { string }

Convenience read of the .metadata.tags array.

globals/asset/typeRef

globals/asset/typeRef(target: RefArg) -> string?

Return the pinned asset_type reference (the type's guid) that the asset is an instance of. Resolve the full type with asset.resolve(asset.typeRef(target)). Returns nil for loose files / assets with no pinned type.

globals/asset/validate

globals/asset/validate(ref: RefArg, type: string?) -> ValidateResult

Validate an asset folder against its type's type.yaml, plus the type's own semantic validation. Structural problems come from type.yaml — missing required files, unsatisfied one_of_group alternatives, and (when allow_unlisted: false) unexpected children. validated = false when no type.yaml is registered — nothing structural to check. On top of that, when the asset's type ships a behavior.luau exporting a top-level validate(assetRef) -> { { code, message, severity? } }, its reported problems (severity defaults to "error") are appended to problems; error-severity problems flip ok to false, warnings leave it untouched. A hook that raises or returns a non-table is itself reported as a validate.hook_failed error problem — a broken hook blocks. A type with no validate export behaves exactly as the structural check alone. world.push calls this per user asset, so a type's semantic validation is enforced at publish time with no further wiring.

globals/asset/warmup

globals/asset/warmup(ref: RefArg, opts: WarmupOpts?) -> WarmupResult

Warm an asset's bytes into CPU memory and follow its declared content dependencies to each referenced asset, deduped by guid. Type-agnostic (reads the generic ref graph) and CPU-only — never touches the GPU. Side-effect-free name resolution (uses asset.guid/asset.deps, not asset.resolve).

  • api
  • reference