Open Asterune
Component definitions

Component definitions

Define typed component schemas and attach component data to Instances.

Components store typed data on Instances. A ComponentDefinition declares a schema. require(definition) returns its runtime Component. An Instance's AddComponent method returns a ComponentHandle for that Instance's data.

Component definitions are evaluated without running the place. They cannot access game, workspace, task, or require. The sandbox provides Component, Enum, value constructors, math, string, table, and basic Luau functions. Evaluation has an 8 MiB memory limit and a bounded execution budget.

Schema

Create a ComponentDefinition named Durability. Its source must return one Component.define result:

Luau
return Component.define({
    Current = Component.number(100, { min = 0, max = 100 }),
    Target = Component.ref("BasePart"),
}, {
    on = { "BasePart" },
    version = 1,
})

A schema supports at most 64 fields. Field names must be valid identifiers. Get, Set, and Instance are reserved by ComponentHandle. Collection types can nest at most four levels.

Component options

OptionBehavior
onAllowed Instance classes. Subclasses are accepted. An empty list permits any class.
replicate"all", "owner", or "none". This can narrow the visibility allowed by the definition's location.
requiresNames of components automatically added with this component. A required component cannot be removed while a dependent component remains.
versionSchema version. The initial version is 1. Older saved rows can be processed by Component:SetMigration.
renamedFromPrevious component name or list of names used to adopt saved data.
docDescription displayed with the component schema.

Field options

All scalar constructors accept doc and renamedFrom options. Numeric fields also accept min and max; number fields accept step. Strings accept maxLength. Lists and maps accept maxItems. Buffers accept maxBytes. Component.list, Component.map, Component.struct, Component.optional, and Component.buffer accept a default option. The value must match the field type and its declared limits; an invalid default rejects the schema.

Numeric values must be finite. Integer fields reject fractions. Runtime numeric assignments are clamped to the declared minimum and maximum. The step option does not quantize runtime assignments. String and collection limits are checked on assignment. Unknown fields, invalid enum members, destroyed reference targets, and references to an incompatible class cause errors.

Reference fields default to nil. onDestroy specifies what happens when the referenced Instance is destroyed:

ValueBehavior
"clear"Clears the reference. This is the default.
"remove"Removes the component holding the reference.
"destroy"Destroys the Instance holding the reference.

Usage

Given a ComponentDefinition at game.ReplicatedStorage.Durability:

Luau
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Durability = require(ReplicatedStorage:WaitForChild("Durability"))
local handle = script.Parent:AddComponent(Durability)
handle.Current = 75

Read and assign declared fields directly. handle:Get() returns a snapshot. handle:Set(values) validates a group of field assignments before applying them. GetComponent returns nil when the component is absent. Reading an existing handle after its component is removed causes an error.

Queries

Query.new requires components and returns handles in the same order as its terms. Filter methods return new queries. Reuse a query across updates to retain its cache and removal cursor.

Luau
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Durability = require(ReplicatedStorage:WaitForChild("Durability"))
local damaged = Query.new(Durability):isA("BasePart")
for instance, durability in damaged do
    if durability.Current == 0 then
        instance:Destroy()
    end
end

Query filters

OperationAccepted terms
Query.new, added, changed, upComponent definitions or component names
with, withoutComponent definitions for component filters; strings for tags

Query results

OperationReturn value
IterationMatching Instance followed by component handles in term order
collectArray of matching Instances without handles
firstFirst matching Instance and handles, or nil when empty
removedList of removed Instances and a boolean indicating whether removal history is complete

See Query for each operation's behavior and failure conditions.

Execution and persistence

Adding or removing a component changes storage structure and requires serial execution. Field writes through ComponentHandle can run in parallel. These writes are recorded and applied at the serial barrier. A writer can read its own pending values. Other writers do not observe those pending values during the parallel phase.

A removed definition does not discard saved component data. That data remains unavailable until a matching definition is restored. Register schema migrations with Component:SetMigration when changing the meaning or layout of saved fields.

Component · ComponentHandle · Query · ComponentDefinition · ComponentService · Systems