ignifx0.x · unpublished
GitHub

Recipes·skills/ignifx/references/recipes/spawn-a-prefab.md

Spawn a prefab

<!-- Generated by `pnpm docs:recipes`. Do not edit by hand. -->

A prefab is a scene file (ADR-0005): the same ignifx.scene format, loaded as a SceneAsset and stamped out with world.instantiate. Instantiation is synchronous, because a SceneAsset arrives with every asset it references already loaded; each copy gets fresh uids and a prefab link back to the file.

Register every component the file names before loading it, or the entity is built without them and the load reports IGX-0307.

The prefab used here is crate.prefab.json, beside this file.

typescript
import { Script, createApp, f32 } from "@ignifx/core";import type { AssetHandle, Entity, SceneAsset, ScriptCallbacks } from "@ignifx/core";/** Bobs its entity up and down. `speed` is a serialized field the prefab file sets. */class Bobber extends Script.define({ speed: f32(1.5) }) implements ScriptCallbacks {  static typeId = "recipes/Bobber";  #elapsed = 0;  update(dt: number): void {    this.#elapsed += dt;    this.transform.localPosition.y = 0.5 + Math.sin(this.#elapsed * this.speed) * 0.2;  }}const canvas = document.querySelector("canvas");if (!(canvas instanceof HTMLCanvasElement)) {  throw new Error("ignifx renders into a <canvas> element.");}const app = await createApp({ canvas, settings: { assets: { root: "assets" } } });app.registerComponents([Bobber]);const crate: AssetHandle<SceneAsset> = await app.assets.loadAsync<SceneAsset>("prefabs/crate.prefab.json");const spawned: Entity[] = [];/** * Stamps one copy of the prefab into the active scene. * * @param x - Where to put it along the world X axis, in metres. * @returns The instance root — one entity, even when the file has several roots. */function spawn(x: number): Entity {  const root = app.world.instantiate(crate.value, {    name: `Crate ${String(spawned.length)}`,    position: { x, y: 0, z: 0 },  });  spawned.push(root);  return root;}for (let index = 0; index < 5; index += 1) {  spawn(index * 1.5 - 3);}await app.start();// Instances outlive the handle: releasing only stops the template from being cached.window.addEventListener("pagehide", () => {  for (const root of spawned) {    root.destroy();  }  crate.release();  app.dispose();});

Source: examples/recipes/spawn-a-prefab/main.ts