Field
The Field namespace — 42 functions.
globals/Field/alias
Field.alias(target: string | { string }, description: string?) -> FieldDesc<any>
Alias for one or more existing fields. An alias is an ACCEPTED key that is not stored itself — it routes the written value to the real field(s) it points at, so a component answers to a caller's natural key without hand-rolling translation code, and both the runtime and the LSP recognise the key.
The key works everywhere the fields it targets do: as a
component.add init key, and as a read and a write on the live
component. Reading it returns what the target(s) hold right now.
Two forms:
Field.alias("radius")— rename. The value is written verbatim to the single target field (running that field's normal coercion, so an alias onto an assetRef field resolves the ref), and reads back as that field's value.Field.alias({ "colorR", "colorG", "colorB" })— fan-out. The value is destructured across the targets: an array{a, b, c}positionally, or a named{r=, g=, b=}/{x=, y=, z=}table by the target's position (r/x, g/y, b/z, a/w). It reads back as an array in target order, soc.color = c.colorround-trips.
An alias never replicates and is never persisted — the fields it targets own their own Sync/NoSync, so no mode argument is taken.
Parameters
targetstring | { string }— A single target field name, or an array of target field names.descriptionstring(optional) — Documents the alias for the LSP; nil to leave it undocumented.
Returns FieldDesc<any> — FieldDesc descriptor with kind = "alias".
type = Field.alias("kind")
color = Field.alias({ "colorR", "colorG", "colorB" })
globals/Field/assetRef
Field.assetRef(category: C & string, default: AssetRef<C> | I | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<C, I>>
Typed asset reference field. C is the asset category — a
singleton string type inferred from the category argument
("material", "mesh", "@user/customCategory", etc.). One
constructor handles every category, including user-registered ones.
Default accepts a resolved AssetRef<C> handle, an identity string
(full @library::path form OR a bare leaf name resolved
category-locally via asset.resolve(identity, category)), or nil.
At registration the engine resolves any string default through the
same category-aware resolver public_newindex uses for runtime
writes, so the first read of public.<field> already returns a
resolved envelope — not a raw string.
Parameters
categoryC & string— Asset category as a string literal ("material","mesh", etc.). Inferred intoC.defaultAssetRef<C> | I | nil(optional) — AssetRef envelope, identity string, or nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<AssetRef<C, I>> descriptor.
material = Field.assetRef("material", "@my-library::materials.gold", Sync)
source = Field.assetRef("bundle", nil, Sync)
globals/Field/bitmask
Field.bitmask(bits: number, default: number?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<number>
Bit-mask number field. bits declares the width the consumer can
address; a default or a write that is not a whole number in
0 .. 2^bits - 1 is rejected, naming the width. Use it wherever a numeric
field is read as a set of bits rather than as a quantity — what the field
reads back is then a mask, so a read-back is evidence the value took.
Parameters
bitsnumber— How many bits wide the mask is, 1..53.defaultnumber(optional) — Numeric default forpublic.<field>, or nil to leave it unset.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDescbitmask constraint.
lightChannels = Field.bitmask(32, 0, Sync)
globals/Field/bool
Field.bool(default: boolean?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<boolean>
Boolean field. nil leaves the field unset.
Parameters
defaultboolean(optional) — Boolean default forpublic.<field>, or nil to leave it unset.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
enabled = Field.bool(true, Sync)
globals/Field/color
Field.color(default: color?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<color>
Color field. Default is a color — either
{r = .., g = .., b = .., a = ..?} or {r, g, b, a?}.
Parameters
defaultcolor(optional) — color default forpublic.<field>.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
tint = Field.color({ 1, 1, 1, 1 }, Sync)
globals/Field/componentRef
Field.componentRef(componentType: T & string, default: ComponentRef<T> | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<ComponentRef<T>>
Typed component reference field. T is the component-type
name — a singleton string type inferred from the componentType
argument ("Camera", "Transform", "@user/Inventory"). The
engine validates the referent exists and is of the declared type
at every write.
Parameters
componentTypeT & string— Component type name as a string literal. Inferred intoT.defaultComponentRef<T> | nil(optional) — ComponentRef envelope or nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<ComponentRef
aimCam = Field.componentRef("Camera", nil, NoSync)
globals/Field/dataRef
Field.dataRef(contract: C & string, default: AssetRef<"data"> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<"data">>
Contract-constrained typed-data reference field. Accepts only
.data assets whose dataType contract chain includes contract.
Rides the assetRef machinery (category "data") — dependency graph,
sync, and rehydration behave exactly like Field.assetRef — with the
contract gate enforced through the generic field-constraint hook on
every write and on the registration-time default.
Parameters
contractC & string— The required dataType contract identity. Inferred intoC.defaultAssetRef<"data"> | string | nil(optional) — AssetRef envelope, identity string, or nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<AssetRef<"data">> descriptor.
weapon = Field.dataRef("weapon", nil, Sync)
globals/Field/entityRef
Field.entityRef(default: EntityRef | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<EntityRef>
Entity reference field. Accepts a live entity proxy (EntityRef),
a raw entity-id string, or nil (no target). Writes are normalised to
the plain id string for storage/replication; reads return a live
EntityRef proxy (or nil), so public.<field>:method() and
public.<field>.id work directly without re-resolving.
Parameters
defaultEntityRef | string | nil(optional) — Live entity proxy, entity-id string, or nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
target = Field.entityRef(nil, Sync)
globals/Field/enum
Field.enum(values: { string }, default: string?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<string>
Closed-set string field. values declares every member; a default or a
write outside the set is rejected with the whole set named. The editor
renders the members as a choice and the LSP completes them.
Parameters
values{ string }— The members, as an array of non-empty, distinct strings.defaultstring(optional) — The default member, or nil to leave the field unset.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDescenum constraint.
fit = Field.enum({ "exact", "hull" }, "hull", Sync)
globals/Field/instantiableRef
Field.instantiableRef(default: AssetRef<any> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<any>>
Scene-instantiable asset reference field — accepts ANY asset whose
type can be instantiated into a scene, gated by CAPABILITY rather than a
hardcoded type list. Rides the assetRef machinery with no category filter
(any asset type resolves), and the generic field-constraint hook rejects,
on every write and on the registration-time default, any asset whose type
defines no instantiate method (ref:canInstantiate() is false). A
new scene-instantiable asset type is accepted here the moment it defines
the hook — no edit to this field or its consumers. The uniform
ref:instantiate(target?, opts?) is how a consumer then instantiates the
assigned asset (Asset.component, a viewport drop, a tool argument).
Parameters
defaultAssetRef<any> | string | nil(optional) — AssetRef envelope, identity string, or nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<AssetRef
source = Field.instantiableRef(nil, Sync)
globals/Field/list
Field.list(element: FieldDesc<any>, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<ListValue>
List field — an array of one repeated element type. The element is the Field constructor descriptor every item conforms to, often a Field.struct for a list of records. The list value is an array of the element's value type. Like Field.struct, the engine descends the element schema to resolve nested asset refs into envelopes, so a stack of structs each holding an asset ref has every ref appear in the asset dependency graph, validates each item, and the LSP type-checks the array. The default value is an empty list. The element declares its own Sync or NoSync for typing; the list's own mode governs replication of the whole array as a unit.
Parameters
elementFieldDesc<any>— The Field constructor descriptor each item conforms to.modeSyncMode— Sync or NoSync — required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<ListValue> — FieldDesc whose value is an array of the element's values.
globals/Field/number
Field.number(default: number?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<number>
Number field. nil leaves the field unset, so a component can treat an
absent value as "derive this from somewhere else" without a second field
recording whether the first one was authored.
Parameters
defaultnumber(optional) — Numeric default forpublic.<field>, or nil to leave it unset.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
positionX = Field.number(0, Sync)
globals/Field/quat
Field.quat(default: quat?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<quat>
Quaternion field. Default is a quat — either
{x = .., y = .., z = .., w = ..} or {x, y, z, w}.
Parameters
defaultquat(optional) — quat default forpublic.<field>.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
rotation = Field.quat({ 0, 0, 0, 1 }, Sync)
globals/Field/range
Field.range(min: number?, max: number?, default: number?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<number>
Bounded number field. min and max declare the interval the value
means something in; a default or a write outside it is rejected with the
interval named. Either bound may be nil, leaving that side open. The value
the field reads back is one the system consuming it can use, and a number
that lands outside is reported where it was written.
Parameters
minnumber(optional) — Lowest accepted value, or nil to leave the low side open.maxnumber(optional) — Highest accepted value, or nil to leave the high side open.defaultnumber(optional) — Numeric default forpublic.<field>, or nil to leave it unset.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDescrange constraint.
volume = Field.range(0, 1, 1, Sync)
globals/Field/resource
Field.resource(category: C & string, default: AssetRef<C> | Handle<C> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<C> | Handle<C>>
Category-gated RESOURCE field — accepts EITHER a persistent
AssetRef<C> OR a live GPU Handle<C>, gated by category. This is the
renderer-facing field type (e.g. Model.model, Model.material, material
texture slots): content can author a persistent asset OR pass a runtime
handle (renderer.<resource>.create(...)); the component bridges either to
the GPU resource. The category gate still holds — an AssetRef<audio> or a
wrong-category handle (a TextureHandle on a "mesh" slot) is a type error
AND a runtime rejection. Use Field.assetRef instead when the field MUST be
a persistent asset (handles rejected).
With Sync, persistent-asset values replicate to peers; a live GPU
handle value is local by construction and stays local — peers keep the
last replicated asset value.
Parameters
categoryC & string— Resource category string literal ("mesh","texture","material", ...). Inferred intoC.defaultAssetRef<C> | Handle<C> | string | nil(optional) —AssetRef<C>/Handle<C>/ identity string / nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<AssetRef
model = Field.resource("mesh", nil, Sync)
globals/Field/string
Field.string(default: string?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<string>
String field. nil leaves the field unset.
Parameters
defaultstring(optional) — String default forpublic.<field>, or nil to leave it unset.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
label = Field.string("hello", Sync)
globals/Field/struct
Field.struct(schema: FieldSchema, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<StructValue>
Struct field — a table whose keys are themselves typed fields. The schema maps each subfield name to its Field constructor descriptor; the struct value is a table holding one value per subfield. Use this instead of Field.table when the table carries asset references or other typed data: the engine descends the schema to resolve nested asset refs into envelopes at registration and at write time, so they appear in the asset dependency graph, validates writes per subfield, and the LSP type-checks the shape. Each subfield declares its own Sync or NoSync for typing; the struct's own mode governs replication of the whole value as a unit.
Parameters
schemaFieldSchema— Map of subfield name to a Field constructor descriptor.modeSyncMode— Sync or NoSync — required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<StructValue> — FieldDesc whose value is a table of the subfields' values.
globals/Field/table
Field.table(default: T, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<T>
Generic table field. T is the table's shape — usually
inferred from the default value, or supplied explicitly via
an explicit ascription Field.table({} :: MyShape, mode) when the default doesn't cover every
key the runtime will write. The engine accepts any Luau table as
a value at write time; per-shape enforcement is opt-in static
typing only.
Parameters
defaultT— Table value to use as the default forpublic.<field>.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
idMap = Field.table({} :: { [string]: string }, NoSync)
globals/Field/taggedRef
Field.taggedRef(tag: string, default: AssetRef<any> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<any>>
Tag-constrained asset reference field — accepts any asset carrying
tag in its .metadata.tags, whatever its type. This is how a slot
states the KIND of asset it takes (a camera behavior, a player visual)
without naming the assets themselves: a new asset becomes assignable the
moment it is tagged, with no edit here or in the consumer. Rides the
assetRef machinery with no category filter — dependency graph, sync and
rehydration behave exactly like Field.assetRef — and the generic
field-constraint hook rejects an untagged asset on every write and on the
registration-time default. asset.list({ fields = { tags = tag } })
enumerates what fits the slot.
Parameters
tagstring— The tag an assigned asset must carry.defaultAssetRef<any> | string | nil(optional) — AssetRef envelope, identity string, or nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<AssetRef
behavior = Field.taggedRef("cameraBehavior", nil, Sync)
globals/Field/vec2
Field.vec2(default: vec2?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<vec2>
Parameters
defaultvec2(optional)modeSyncModemarker(SerializedMode | string | FieldOptions)(optional)
Returns FieldDesc<vec2>
globals/Field/vec3
Field.vec3(default: vec3?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<vec3>
Vec3 field. Default is a vec3 — either {x = .., y = .., z = ..}
or the 3-element array form {x, y, z}.
Parameters
defaultvec3(optional) — vec3 default forpublic.<field>.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
offset = Field.vec3({ 0, 0, 0 }, Sync)
typed/builtin//modules/field/Field/alias
Field.alias(target: string | { string }, description: string?) -> FieldDesc<any>
Alias for one or more existing fields. An alias is an ACCEPTED key that is not stored itself — it routes the written value to the real field(s) it points at, so a component answers to a caller's natural key without hand-rolling translation code, and both the runtime and the LSP recognise the key.
The key works everywhere the fields it targets do: as a
component.add init key, and as a read and a write on the live
component. Reading it returns what the target(s) hold right now.
Two forms:
Field.alias("radius")— rename. The value is written verbatim to the single target field (running that field's normal coercion, so an alias onto an assetRef field resolves the ref), and reads back as that field's value.Field.alias({ "colorR", "colorG", "colorB" })— fan-out. The value is destructured across the targets: an array{a, b, c}positionally, or a named{r=, g=, b=}/{x=, y=, z=}table by the target's position (r/x, g/y, b/z, a/w). It reads back as an array in target order, soc.color = c.colorround-trips.
An alias never replicates and is never persisted — the fields it targets own their own Sync/NoSync, so no mode argument is taken.
Parameters
targetstring | { string }— A single target field name, or an array of target field names.descriptionstring(optional) — Documents the alias for the LSP; nil to leave it undocumented.
Returns FieldDesc<any> — FieldDesc descriptor with kind = "alias".
type = Field.alias("kind")
color = Field.alias({ "colorR", "colorG", "colorB" })
typed/builtin//modules/field/Field/assetRef
Field.assetRef(category: C & string, default: AssetRef<C> | I | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<C, I>>
Typed asset reference field. C is the asset category — a
singleton string type inferred from the category argument
("material", "mesh", "@user/customCategory", etc.). One
constructor handles every category, including user-registered ones.
Default accepts a resolved AssetRef<C> handle, an identity string
(full @library::path form OR a bare leaf name resolved
category-locally via asset.resolve(identity, category)), or nil.
At registration the engine resolves any string default through the
same category-aware resolver public_newindex uses for runtime
writes, so the first read of public.<field> already returns a
resolved envelope — not a raw string.
Parameters
categoryC & string— Asset category as a string literal ("material","mesh", etc.). Inferred intoC.defaultAssetRef<C> | I | nil(optional) — AssetRef envelope, identity string, or nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<AssetRef<C, I>> descriptor.
material = Field.assetRef("material", "@my-library::materials.gold", Sync)
source = Field.assetRef("bundle", nil, Sync)
typed/builtin//modules/field/Field/bitmask
Field.bitmask(bits: number, default: number?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<number>
Bit-mask number field. bits declares the width the consumer can
address; a default or a write that is not a whole number in
0 .. 2^bits - 1 is rejected, naming the width. Use it wherever a numeric
field is read as a set of bits rather than as a quantity — what the field
reads back is then a mask, so a read-back is evidence the value took.
Parameters
bitsnumber— How many bits wide the mask is, 1..53.defaultnumber(optional) — Numeric default forpublic.<field>, or nil to leave it unset.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDescbitmask constraint.
lightChannels = Field.bitmask(32, 0, Sync)
typed/builtin//modules/field/Field/bool
Field.bool(default: boolean?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<boolean>
Boolean field. nil leaves the field unset.
Parameters
defaultboolean(optional) — Boolean default forpublic.<field>, or nil to leave it unset.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
enabled = Field.bool(true, Sync)
typed/builtin//modules/field/Field/color
Field.color(default: color?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<color>
Color field. Default is a color — either
{r = .., g = .., b = .., a = ..?} or {r, g, b, a?}.
Parameters
defaultcolor(optional) — color default forpublic.<field>.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
tint = Field.color({ 1, 1, 1, 1 }, Sync)
typed/builtin//modules/field/Field/componentRef
Field.componentRef(componentType: T & string, default: ComponentRef<T> | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<ComponentRef<T>>
Typed component reference field. T is the component-type
name — a singleton string type inferred from the componentType
argument ("Camera", "Transform", "@user/Inventory"). The
engine validates the referent exists and is of the declared type
at every write.
Parameters
componentTypeT & string— Component type name as a string literal. Inferred intoT.defaultComponentRef<T> | nil(optional) — ComponentRef envelope or nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<ComponentRef
aimCam = Field.componentRef("Camera", nil, NoSync)
typed/builtin//modules/field/Field/dataRef
Field.dataRef(contract: C & string, default: AssetRef<"data"> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<"data">>
Contract-constrained typed-data reference field. Accepts only
.data assets whose dataType contract chain includes contract.
Rides the assetRef machinery (category "data") — dependency graph,
sync, and rehydration behave exactly like Field.assetRef — with the
contract gate enforced through the generic field-constraint hook on
every write and on the registration-time default.
Parameters
contractC & string— The required dataType contract identity. Inferred intoC.defaultAssetRef<"data"> | string | nil(optional) — AssetRef envelope, identity string, or nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<AssetRef<"data">> descriptor.
weapon = Field.dataRef("weapon", nil, Sync)
typed/builtin//modules/field/Field/entityRef
Field.entityRef(default: EntityRef | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<EntityRef>
Entity reference field. Accepts a live entity proxy (EntityRef),
a raw entity-id string, or nil (no target). Writes are normalised to
the plain id string for storage/replication; reads return a live
EntityRef proxy (or nil), so public.<field>:method() and
public.<field>.id work directly without re-resolving.
Parameters
defaultEntityRef | string | nil(optional) — Live entity proxy, entity-id string, or nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
target = Field.entityRef(nil, Sync)
typed/builtin//modules/field/Field/enum
Field.enum(values: { string }, default: string?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<string>
Closed-set string field. values declares every member; a default or a
write outside the set is rejected with the whole set named. The editor
renders the members as a choice and the LSP completes them.
Parameters
values{ string }— The members, as an array of non-empty, distinct strings.defaultstring(optional) — The default member, or nil to leave the field unset.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDescenum constraint.
fit = Field.enum({ "exact", "hull" }, "hull", Sync)
typed/builtin//modules/field/Field/instantiableRef
Field.instantiableRef(default: AssetRef<any> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<any>>
Scene-instantiable asset reference field — accepts ANY asset whose
type can be instantiated into a scene, gated by CAPABILITY rather than a
hardcoded type list. Rides the assetRef machinery with no category filter
(any asset type resolves), and the generic field-constraint hook rejects,
on every write and on the registration-time default, any asset whose type
defines no instantiate method (ref:canInstantiate() is false). A
new scene-instantiable asset type is accepted here the moment it defines
the hook — no edit to this field or its consumers. The uniform
ref:instantiate(target?, opts?) is how a consumer then instantiates the
assigned asset (Asset.component, a viewport drop, a tool argument).
Parameters
defaultAssetRef<any> | string | nil(optional) — AssetRef envelope, identity string, or nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<AssetRef
source = Field.instantiableRef(nil, Sync)
typed/builtin//modules/field/Field/list
Field.list(element: FieldDesc<any>, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<ListValue>
List field — an array of one repeated element type. The element is the Field constructor descriptor every item conforms to, often a Field.struct for a list of records. The list value is an array of the element's value type. Like Field.struct, the engine descends the element schema to resolve nested asset refs into envelopes, so a stack of structs each holding an asset ref has every ref appear in the asset dependency graph, validates each item, and the LSP type-checks the array. The default value is an empty list. The element declares its own Sync or NoSync for typing; the list's own mode governs replication of the whole array as a unit.
typed/builtin//modules/field/Field/number
Field.number(default: number?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<number>
Number field. nil leaves the field unset, so a component can treat an
absent value as "derive this from somewhere else" without a second field
recording whether the first one was authored.
Parameters
defaultnumber(optional) — Numeric default forpublic.<field>, or nil to leave it unset.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
positionX = Field.number(0, Sync)
typed/builtin//modules/field/Field/quat
Field.quat(default: quat?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<quat>
Quaternion field. Default is a quat — either
{x = .., y = .., z = .., w = ..} or {x, y, z, w}.
Parameters
defaultquat(optional) — quat default forpublic.<field>.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
rotation = Field.quat({ 0, 0, 0, 1 }, Sync)
typed/builtin//modules/field/Field/range
Field.range(min: number?, max: number?, default: number?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<number>
Bounded number field. min and max declare the interval the value
means something in; a default or a write outside it is rejected with the
interval named. Either bound may be nil, leaving that side open. The value
the field reads back is one the system consuming it can use, and a number
that lands outside is reported where it was written.
Parameters
minnumber(optional) — Lowest accepted value, or nil to leave the low side open.maxnumber(optional) — Highest accepted value, or nil to leave the high side open.defaultnumber(optional) — Numeric default forpublic.<field>, or nil to leave it unset.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDescrange constraint.
volume = Field.range(0, 1, 1, Sync)
typed/builtin//modules/field/Field/resource
Field.resource(category: C & string, default: AssetRef<C> | Handle<C> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<C> | Handle<C>>
Category-gated RESOURCE field — accepts EITHER a persistent
AssetRef<C> OR a live GPU Handle<C>, gated by category. This is the
renderer-facing field type (e.g. Model.model, Model.material, material
texture slots): content can author a persistent asset OR pass a runtime
handle (renderer.<resource>.create(...)); the component bridges either to
the GPU resource. The category gate still holds — an AssetRef<audio> or a
wrong-category handle (a TextureHandle on a "mesh" slot) is a type error
AND a runtime rejection. Use Field.assetRef instead when the field MUST be
a persistent asset (handles rejected).
With Sync, persistent-asset values replicate to peers; a live GPU
handle value is local by construction and stays local — peers keep the
last replicated asset value.
Parameters
categoryC & string— Resource category string literal ("mesh","texture","material", ...). Inferred intoC.defaultAssetRef<C> | Handle<C> | string | nil(optional) —AssetRef<C>/Handle<C>/ identity string / nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<AssetRef
model = Field.resource("mesh", nil, Sync)
typed/builtin//modules/field/Field/string
Field.string(default: string?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<string>
String field. nil leaves the field unset.
Parameters
defaultstring(optional) — String default forpublic.<field>, or nil to leave it unset.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
label = Field.string("hello", Sync)
typed/builtin//modules/field/Field/struct
Field.struct(schema: FieldSchema, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<StructValue>
Struct field — a table whose keys are themselves typed fields. The schema maps each subfield name to its Field constructor descriptor; the struct value is a table holding one value per subfield. Use this instead of Field.table when the table carries asset references or other typed data: the engine descends the schema to resolve nested asset refs into envelopes at registration and at write time, so they appear in the asset dependency graph, validates writes per subfield, and the LSP type-checks the shape. Each subfield declares its own Sync or NoSync for typing; the struct's own mode governs replication of the whole value as a unit.
Parameters
schemaFieldSchema— Map of subfield name to a Field constructor descriptor.modeSyncMode— Sync or NoSync — required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<StructValue> — FieldDesc whose value is a table of the subfields' values.
typed/builtin//modules/field/Field/table
Field.table(default: T, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<T>
Generic table field. T is the table's shape — usually
inferred from the default value, or supplied explicitly via
an explicit ascription Field.table({} :: MyShape, mode) when the default doesn't cover every
key the runtime will write. The engine accepts any Luau table as
a value at write time; per-shape enforcement is opt-in static
typing only.
Parameters
defaultT— Table value to use as the default forpublic.<field>.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
idMap = Field.table({} :: { [string]: string }, NoSync)
typed/builtin//modules/field/Field/taggedRef
Field.taggedRef(tag: string, default: AssetRef<any> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<any>>
Tag-constrained asset reference field — accepts any asset carrying
tag in its .metadata.tags, whatever its type. This is how a slot
states the KIND of asset it takes (a camera behavior, a player visual)
without naming the assets themselves: a new asset becomes assignable the
moment it is tagged, with no edit here or in the consumer. Rides the
assetRef machinery with no category filter — dependency graph, sync and
rehydration behave exactly like Field.assetRef — and the generic
field-constraint hook rejects an untagged asset on every write and on the
registration-time default. asset.list({ fields = { tags = tag } })
enumerates what fits the slot.
Parameters
tagstring— The tag an assigned asset must carry.defaultAssetRef<any> | string | nil(optional) — AssetRef envelope, identity string, or nil.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc<AssetRef
behavior = Field.taggedRef("cameraBehavior", nil, Sync)
typed/builtin//modules/field/Field/vec2
Field.vec2(default: vec2?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<vec2>
Parameters
defaultvec2(optional)modeSyncModemarker(SerializedMode | string | FieldOptions)(optional)
Returns FieldDesc<vec2>
typed/builtin//modules/field/Field/vec3
Field.vec3(default: vec3?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<vec3>
Vec3 field. Default is a vec3 — either {x = .., y = .., z = ..}
or the 3-element array form {x, y, z}.
Parameters
defaultvec3(optional) — vec3 default forpublic.<field>.modeSyncMode—SyncorNoSync— required.marker(SerializedMode | string | FieldOptions)(optional) —Serialized, a description string, or a{ serialized, description }options table; omit for neither.
Returns FieldDesc
offset = Field.vec3({ 0, 0, 0 }, Sync)