GameObject API: spawn, find, hierarchy, activation, name, destroy (#82) #94

Merged
crowmaki merged 2 commits from issue-82-gameobject-api into main 2026-09-06 03:46:31 +00:00
Owner

Closes #82. Part of #75.

What

A Script reaches GameObjects with the names Unity uses, through a userdata carrying the GameObject Handle and cached per Handle in a weak table, so == is identity within a frame.

  • Properties: name (read/write), parent (read/write, nil detaches to the root), active (read/write), activeInHierarchy (read-only).
  • Methods: IsAlive, SetActive, GetChildren (sibling order), Destroy.
  • GameObject.new() / GameObject.new(name, parent) create in the top Scene, or the parent's Scene. GameObject.Find(displayPath) resolves a Display Path or answers nil.
  • A global Destroy(go) matches go:Destroy(). self.gameObject inside a Component method is the owner; a Script Schema may not name a field gameObject.
  • Every access to a dead Handle raises naming the operation (read name on a destroyed GameObject, GetChildren on a destroyed GameObject). IsAlive never raises.
  • The luau Plugin now shares one weak-table cache helper and one Userdata_Tag enum between Component instances and GameObjects.

One reading to confirm

The issue says Destroy leaves the GameObject "alive until the next Structural Flush and gone after it", and also that IsAlive answers "false at once after destruction". Core already makes a destroyed Handle stop validating at once and releases storage at the flush, so this follows Core: IsAlive is false immediately, OnDestroy and storage release wait for the flush. The test observes the flush boundary through OnDestroy.

Tests

tests/luau/gameobject_test.odin covers every acceptance criterion from Luau source strings, checked against scene_object_count, gameobject_name, gameobject_parent, gameobject_is_active and gameobject_is_active_in_hierarchy.

just check and just test pass (437 tests).

Closes #82. Part of #75. ## What A Script reaches GameObjects with the names Unity uses, through a userdata carrying the GameObject Handle and cached per Handle in a weak table, so `==` is identity within a frame. - Properties: `name` (read/write), `parent` (read/write, `nil` detaches to the root), `active` (read/write), `activeInHierarchy` (read-only). - Methods: `IsAlive`, `SetActive`, `GetChildren` (sibling order), `Destroy`. - `GameObject.new()` / `GameObject.new(name, parent)` create in the top Scene, or the parent's Scene. `GameObject.Find(displayPath)` resolves a Display Path or answers `nil`. - A global `Destroy(go)` matches `go:Destroy()`. `self.gameObject` inside a Component method is the owner; a Script Schema may not name a field `gameObject`. - Every access to a dead Handle raises naming the operation (`read name on a destroyed GameObject`, `GetChildren on a destroyed GameObject`). `IsAlive` never raises. - The luau Plugin now shares one weak-table cache helper and one `Userdata_Tag` enum between Component instances and GameObjects. ## One reading to confirm The issue says Destroy leaves the GameObject "alive until the next Structural Flush and gone after it", and also that `IsAlive` answers "false at once after destruction". Core already makes a destroyed Handle stop validating at once and releases storage at the flush, so this follows Core: `IsAlive` is false immediately, `OnDestroy` and storage release wait for the flush. The test observes the flush boundary through `OnDestroy`. ## Tests `tests/luau/gameobject_test.odin` covers every acceptance criterion from Luau source strings, checked against `scene_object_count`, `gameobject_name`, `gameobject_parent`, `gameobject_is_active` and `gameobject_is_active_in_hierarchy`. `just check` and `just test` pass (437 tests).
A Script reaches GameObjects through a userdata carrying the Handle, cached
per Handle in a weak table. The metatable exposes name, parent, active and
activeInHierarchy as properties and IsAlive, SetActive, GetChildren and
Destroy as methods. GameObject.new and GameObject.Find create and resolve;
a global Destroy matches go:Destroy(). self.gameObject inside a Component
method is the owner. Every access to a dead Handle raises naming the
operation, except IsAlive.
Review follow-ups for #82: one weak-table cache helper and one Userdata_Tag
enum serve both userdata kinds; GameObject.new validates its arguments before
it creates anything; an unknown key on a dead Handle raises like a known one;
a Script Schema may not name a field gameObject, since that is the owner
property. The Destroy test now observes the Structural Flush through
OnDestroy rather than through a count that cannot see it.
crowmaki deleted branch issue-82-gameobject-api 2026-09-06 03:46:31 +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!94
No description provided.