Skip to content

[Framework] Add an optional Unity-like component and lifecycle facade #143

Description

@proggeramlug

Parent: #126

Problem

Bloom has a broad raylib-like flat API and world/prefab data, but lacks a small Unity-like behavior/lifecycle layer tying entities, transforms, rendering, physics, animation, audio, serialization, and updates together. Games otherwise create their own conventions, duplicate cleanup and handle bookkeeping, and become difficult to compose.

Outcome

An optional, thin TypeScript component/entity facade over existing low-level APIs. It should make common scene behavior familiar and composable without forcing ECS complexity or removing immediate-mode usage.

Public model

Define:

  • stable Entity identity with hierarchical transform;
  • typed components with explicit ownership and serialization IDs;
  • lifecycle hooks such as onCreate, onStart, onUpdate, onFixedUpdate, onEnable, onDisable, onDestroy (exact names may vary);
  • deterministic update order and a supported dependency/order mechanism;
  • scene/prefab instantiate/destroy with cleanup of native handles;
  • component lookup that is type-safe within Perry's supported TypeScript subset;
  • bridges for renderer/model, camera/light, rigid body/collider, animator, audio source/listener, and user scripts.

The minimum game should still fit in a short file. Low-level draw* and handle APIs remain available.

Ownership and lifecycle rules

  • State whether entity or component owns each native handle.
  • Destruction is idempotent and happens at a safe frame boundary.
  • Parent destroy, reparent, enable/disable, scene unload, and async asset completion have deterministic behavior.
  • Fixed physics updates are separated from variable render updates with interpolation rules.
  • A component cannot receive update after destruction or before required dependencies are ready.
  • Errors include entity/component names/IDs rather than only native handles.

Serialization/prefabs

  • Register component type/version and encode stable data only; runtime handles are reconstructed.
  • Unknown component versions/types survive or fail according to a documented forward-compatibility policy.
  • Prefab override semantics are explicit and tested.
  • User scripts can define serializable fields within the Perry-supported type subset.

Acceptance criteria

  • A documented sample creates a player entity with transform, rendered model, rigid body, animator, audio source, and user behavior without manual native-handle cleanup.
  • Lifecycle order is unit-tested across create/enable/disable/reparent/destroy/scene unload.
  • Fixed update remains deterministic under variable render frame times.
  • Prefab instantiate/save/load preserves component data and overrides across a versioned round-trip.
  • Destroying scenes/entities releases owned renderer/physics/audio/asset references with leak counters at zero.
  • Async asset completion after entity destruction is safe.
  • The component layer adds negligible allocation to an unchanged frame; profile a 10,000-entity no-op/update case.
  • Existing immediate-mode and low-level scene examples require no migration.

Likely files

  • new module under src/ (for example src/components/ or src/game/)
  • src/world/ prefab/serialization/version code
  • existing scene/models/physics/audio wrappers
  • small native support only where lifecycle-safe batching cannot be expressed through current FFI

Non-goals

  • A data-oriented ECS rewrite of the native engine.
  • Editor reflection/inspector UI.
  • Replacing the raylib-style API.

Dependencies

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions