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:
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
| Option | Behavior |
|---|---|
on | Allowed 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. |
requires | Names of components automatically added with this component. A required component cannot be removed while a dependent component remains. |
version | Schema version. The initial version is 1. Older saved rows can be processed by Component:SetMigration. |
renamedFrom | Previous component name or list of names used to adopt saved data. |
doc | Description 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:
| Value | Behavior |
|---|---|
"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:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Durability = require(ReplicatedStorage:WaitForChild("Durability"))
local handle = script.Parent:AddComponent(Durability)
handle.Current = 75Read 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.
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
endQuery filters
| Operation | Accepted terms |
|---|---|
Query.new, added, changed, up | Component definitions or component names |
with, without | Component definitions for component filters; strings for tags |
Query results
| Operation | Return value |
|---|---|
| Iteration | Matching Instance followed by component handles in term order |
collect | Array of matching Instances without handles |
first | First matching Instance and handles, or nil when empty |
removed | List 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.
Related APIs
Component · ComponentHandle · Query · ComponentDefinition · ComponentService · Systems