> For the complete documentation index, see [llms.txt](https://studio-docs.sandbox.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://studio-docs.sandbox.game/the-editor/how-to-register-a-placeable-game-class.md).

# How to register a placeable GameClass

Engine objects (lights, Model Mesh Node, Door Node) are already in the Place panel and the Outliner **+** list. Anything you write is a **GameClass**: a TypeScript class with `@ENGINE.GameClass()` that extends `ENGINE.SceneNode` (or a pawn / other engine type).

After `pnpm build` and **Build Project**, it shows up as `GAME.YourClassName`. You place it like an engine node, then save it as a prefab if you will stamp it more than twice.

Do not name your class `*Actor`. Engine v14 treats `Actor` as an error. The Outliner still shows **SceneNode**. Folder names on disk (even `Actors/`) are not class names.

Full rules for generated files and asset paths: [Project code fundamentals](/best-practices/project-code-fundamentals.md). Folder map: [Project Structure](/best-practices/project-structure.md).

## Engine node vs your class

| Kind   | In JSON / prefabs  | Where it lives              |
| ------ | ------------------ | --------------------------- |
| Engine | `ENGINE.ClassName` | Shipped with the editor     |
| Yours  | `GAME.ClassName`   | A file you add under `src/` |

`@ENGINE.property()` fields appear in the Inspector and save with the scene or prefab.

{% stepper %}
{% step %}

## Add a class under src/

Create a new `.ts` file in `src/` (group it by what it is in the game, not by engine type). Extend `ENGINE.SceneNode`. Decorate the class with `@ENGINE.GameClass()`. Do not use `EngineClass`.

```typescript
import * as ENGINE from '@gnsx/genesys.js';

@ENGINE.GameClass()
export class BeaconNode extends ENGINE.SceneNode {
  @ENGINE.property({
    type: 'number',
    min: 0,
    category: 'Gameplay',
  })
  public range = 8;
}
```

Keep `src/game.ts` where it is. Never edit `src/auto-imports.ts` or `src/game-data.ts`.
{% endstep %}

{% step %}

## Build in the terminal, then in Studio

From the project root (the folder that contains `package.json`):

```
pnpm build
```

That typechecks and regenerates `auto-imports.ts` and `game-data.ts`.

Then in Sandbox Studio: **Build Project**, or `Ctrl+B` / `Cmd+B`. The agent can run the same rebuild through [Sandbox Studio MCP](/working-efficiently-with-ai/set-up-and-use-sandbox-studio-mcp.md).
{% endstep %}

{% step %}

## Place the class in the scene

Search the **Place** panel or the Inspector **+** list for the display name (for example `Beacon Node` / `GAME.BeaconNode`). Add it the same way you add a Door Node or VFX Node.

Set Inspector fields you marked with `@ENGINE.property()`. Save with `Ctrl+S` / `Cmd+S`.
{% endstep %}

{% step %}

## Save as Prefab when you will stamp it

If you would place this setup more than twice, right-click the node in the Outliner and **Save as Prefab**. Prefab JSON uses `"$bc": "GAME.BeaconNode"`. Place copies by dragging the `.prefab.json`. See [How to Set Up a Prefab](/the-editor/how-to-set-up-a-prefab.md).

The player still spawns from GameMode, not from a placed player prefab. See [How to spawn the player and place NPC prefabs](/the-editor/how-to-spawn-the-player-and-place-npc-prefabs.md).
{% endstep %}
{% endstepper %}

## When to write a class vs use an engine node

Use an engine node when it already does the job: Model Mesh, lights, Door, Pickup, Trigger Zone, VFX Node, Sound Node.

Write a GameClass when you need your own Inspector fields, Play-mode behaviour, or a tree the engine does not ship (a custom beacon, a custom NPC pawn). Prefer a `.vfx.json` plus VFX Node for particles you can author in the VFX Editor. Custom slash trails and similar effects that must follow a bone are GameClass / TypeScript, not a VFX file.

## Common mistakes

| What went wrong                                              | What to do                                                              |
| ------------------------------------------------------------ | ----------------------------------------------------------------------- |
| Class missing from Place after you saved the `.ts` file      | Run `pnpm build`, then **Build Project** (`Ctrl+B` / `Cmd+B`).          |
| Edited `auto-imports.ts` and the change vanished             | Put the class in your own file under `src/`. Generated files overwrite. |
| Named the class `SomethingActor`                             | Rename to a SceneNode-era name. `Actor` fails lint.                     |
| Hand-edited the `.genesys-scene` to insert `GAME.BeaconNode` | Place in the editor, or ask the agent through MCP.                      |
| Used `EngineClass` on your type                              | Use `@ENGINE.GameClass()` only.                                         |

## What You've Done

You can add a `GAME.` class, rebuild so it appears in Place, set Inspector properties, and wrap it in a prefab. Next: [Project code fundamentals](/best-practices/project-code-fundamentals.md) for paths and lint, or [How to Set Up a Prefab](/the-editor/how-to-set-up-a-prefab.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://studio-docs.sandbox.game/the-editor/how-to-register-a-placeable-game-class.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
