Components from Luau: AddComponent, GetComponent, GetComponents, Destroy (#83) #95

Merged
crowmaki merged 1 commit from components-from-luau-83 into main 2026-09-06 05:22:50 +00:00
Owner

Closes #83. Part of #75.

What

A Script composes GameObjects at runtime.

  • go:AddComponent(class) attaches a Component, runs Awake, and returns the instance. class is the table Component.define returned or a Schema name string; an unknown name raises.
  • GetComponent and GetComponents on a GameObject or on self accept the same two forms. An unknown name answers nil or an empty table.
  • A Component no Script defined comes back as a generic userdata answering gameObject, IsAlive, Destroy and the two lookups. Any field read or write raises naming the Schema.
  • Destroy(component) and component:Destroy() queue removal for the next Structural Flush. The global Destroy dispatches on the userdata tag.
  • The per-frame walk decides its instances before it starts. Everything alive and active at frame start updates that frame, even when its GameObject is destroyed partway through, and anything added mid-frame waits for the next frame. Deactivation still takes effect at once.
  • The test harness start takes companion Plugins ahead of luau, so a test can register an Odin Component.

Two readings to confirm

  • The issue lists three members on a generic userdata. GetComponent and GetComponents are also answered there, since they only need an owner.
  • A Component queued for removal still reads its fields until the flush, which is what Core's component_data already allows. The mid-frame destroy case relies on it.

Tests

tests/luau/composition_test.odin covers every acceptance criterion from Luau source strings, checked against gameobject_component_count, component_count and component_is_alive.

just check and just test pass (443 tests).

Closes #83. Part of #75. ## What A Script composes GameObjects at runtime. - `go:AddComponent(class)` attaches a Component, runs `Awake`, and returns the instance. `class` is the table `Component.define` returned or a Schema name string; an unknown name raises. - `GetComponent` and `GetComponents` on a GameObject or on `self` accept the same two forms. An unknown name answers `nil` or an empty table. - A Component no Script defined comes back as a generic userdata answering `gameObject`, `IsAlive`, `Destroy` and the two lookups. Any field read or write raises naming the Schema. - `Destroy(component)` and `component:Destroy()` queue removal for the next Structural Flush. The global `Destroy` dispatches on the userdata tag. - The per-frame walk decides its instances before it starts. Everything alive and active at frame start updates that frame, even when its GameObject is destroyed partway through, and anything added mid-frame waits for the next frame. Deactivation still takes effect at once. - The test harness `start` takes companion Plugins ahead of luau, so a test can register an Odin Component. ## Two readings to confirm - The issue lists three members on a generic userdata. `GetComponent` and `GetComponents` are also answered there, since they only need an owner. - A Component queued for removal still reads its fields until the flush, which is what Core's `component_data` already allows. The mid-frame destroy case relies on it. ## Tests `tests/luau/composition_test.odin` covers every acceptance criterion from Luau source strings, checked against `gameobject_component_count`, `component_count` and `component_is_alive`. `just check` and `just test` pass (443 tests).
Part of #75.

A Script composes GameObjects at runtime. `go:AddComponent(class)`
attaches a Component, runs Awake, and returns the instance.
`GetComponent` and `GetComponents` on a GameObject or on `self` accept
the table Component.define returned or a Schema name string, so an
Odin-registered Component is reachable too. One the Scripts did not
define comes back as a generic userdata answering gameObject, IsAlive,
Destroy and the lookups, and raises on any field. `Destroy(component)`
and `component:Destroy()` queue removal for the next Structural Flush.

The per-frame walk now decides its instances before it starts: every
instance alive and active at frame start updates that frame, even when
its GameObject is destroyed partway through, and one added mid-frame
waits for the next. Deactivation still takes effect at once.

The test harness takes companion Plugins ahead of luau so a test can
register an Odin Component.
crowmaki deleted branch components-from-luau-83 2026-09-06 05:22:50 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
crowmaki/cinnabar!95
No description provided.