> For the complete documentation index, see [llms.txt](https://stoneforgeteam.gitbook.io/stoneforgeteam-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://stoneforgeteam.gitbook.io/stoneforgeteam-docs/gml-and-c-code/instances.md).

# Instances and objects

An **instance** is one thing in the room: the player, an enemy, an item on the ground, a menu button. Each is an instance of a GameMaker **object** (`o_player`, `o_loot`...), and objects inherit from each other (`o_player` is an `o_unit`).

StoneForge gives you instances two ways:

* **`Instance`**: untyped, every variable by name: `instance["HP"]`.
* **A generated object class**, from `StoneForge.Objects`: typed, with the object's own variables as properties: `player.HP`. Every class derives from `GameInstance`, and follows the game's inheritance (`o_player : o_unit : ...`).

```csharp
using StoneForge.Objects;

o_player? player = Instances.First<o_player>(GameObjectId.o_player);
if (player != null)
{
    double hp = player.HP;             // the object's own variable, typed
    player.X += 16;                    // a built-in, on every GameInstance
    player.Instance.Set("my_flag", true); // anything else, by name
}
```

## Finding instances

| `Instances`                                                            |                                                                                                            |
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `First<T>(GameObjectId obj)`                                           | The first instance of an object (or a child of it), or `null`.                                             |
| `All<T>(GameObjectId obj)`                                             | Every instance, as `T`.                                                                                    |
| `All(GameObjectId obj)`, `All(int objectIndex)`, `All(GameObject obj)` | Every instance, untyped (the last for a [mod's own object](/stoneforgeteam-docs/content/game-objects.md)). |
| `Nearest<T>(x, y, GameObjectId obj)`, `Nearest(x, y, int objectIndex)` | The one nearest a point.                                                                                   |
| `Count(int objectIndex)`                                               | How many there are (not those culled).                                                                     |

```csharp
foreach (var enemy in Instances.All<GameInstance>(GameObjectId.o_enemy))
    if (enemy.Exists && enemy.IsA((int)GameObjectId.o_enemy))
        count++;
```

`Gm` has the common built-ins typed: `Gm.InstanceExists(obj)`, `Gm.InstanceNumber(obj)`, `Gm.Create<T>(x, y, depth, obj)`, `Gm.ObjectIsAncestor`, `Gm.AssetGetIndex(name)`, and where the game is: `Gm.InMainMenu`, `Gm.InGame`, `Gm.Room`.

## GameInstance

Every typed instance has GameMaker's built-in variables as properties:

|                                                                                                                |                                                                                         |
| -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| `X`, `Y`, `XPrevious`, `YPrevious`, `Depth`                                                                    | Where it is.                                                                            |
| `Visible`, `SpriteIndex`, `ImageIndex`, `ImageSpeed`, `ImageXScale`, `ImageYScale`, `ImageAngle`, `ImageAlpha` | How it's drawn.                                                                         |
| `ObjectIndex`, `IsA(obj)`, `Id`                                                                                | What it is (compare `ObjectIndex` with `(int)GameObjectId.o_...`).                      |
| `Exists`, `Destroy()`                                                                                          | Whether it's still there; remove it (its Destroy event runs).                           |
| `Alarm[0..11]`                                                                                                 | Its alarms: steps until each goes off, `-1` when off. `player.Alarm[2] = -1` stops one. |
| `Instance`                                                                                                     | The untyped instance underneath.                                                        |

The generated classes add each object's own variables, the ones its events assign: `player.HP`, `player.max_hp`, `nav.buttonsOffset`.

## Instance

|                                               |                                                                |
| --------------------------------------------- | -------------------------------------------------------------- |
| `this[name]`, `Get(name)`, `Set(name, value)` | A variable, by name. Missing: `undefined`. Setting creates it. |

On a typed instance, set variables by name with `Set`: `player.Instance.Set("my_flag", true)`. C# won't let you assign through the indexer of a value a property returns (`player.Instance["my_flag"] = true` doesn't compile); a local or field works either way. | `Exists`, `IsNone`, `Id`, `Instance.FromId(id)` | Whether it's there; the GameMaker id; an instance from an id. | | `Instance.Of(value)` | The instance a value the game keeps names - a reference, or its id as a number (a unit's target, an effect's owner) - or none (`noone`, `-4`, `undefined`). | | `As<T>()` | As a generated class: `instance.As<o_player>()`. | | `Persist()` | A reference by id, safe to keep between callbacks (see below). | | `Destroy(runDestroyEvent = true)` | Remove it, culled or not. | | `IsCulled`, `IsGone` | See [culling](#culling). | | `Alarm[...]` | Its alarms. |

## Keeping instances between callbacks

An `Instance` handed to an event or hook can be used freely inside that callback. To keep one for later - in a field, between frames - keep it by id:

```csharp
private Instance _target;

Events.o_player.Step_0.After(context, player => _target = player.Instance.Persist());

public void Tick(double deltaTime)
{
    if (_target.Exists)
        _target["image_alpha"] = 0.5;
}
```

Always check `Exists` before using a kept instance: the game may have destroyed it since. Ids identify instances in the running game only, not across saves.

## Culling

To save work, the game *culls* some instances that are off screen - ground loot, decorations - deactivating them until they're on screen again. A culled instance is still in the world, but GameMaker's own `with` and `instance_exists` skip it, and its own variables can't be read or set (its built-ins, such as `x` and `object_index`, can).

* `Instances.All(..., includeCulled: true)` lists culled instances too.
* `instance.IsCulled`: deactivated by the game, still in the world.
* `instance.IsGone`: really gone (destroyed, picked up); `Exists` is false for a culled one too.
* `instance.Destroy()` handles culled instances safely.

Keep a mod's data about an instance by its id, not on the instance, so it survives culling:

```csharp
using System.Linq;

var loot = Instances.All(GameObjectId.o_loot, includeCulled: true);
int offScreen = loot.Count(item => item.IsCulled);
```

## Creating instances

```csharp
var mark = Gm.Create<GameInstance>(x, y, depth: 0, GameObjectId.o_invisible_mark);
```

For objects of your own, with events written in C#, see [Game objects](/stoneforgeteam-docs/content/game-objects.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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://stoneforgeteam.gitbook.io/stoneforgeteam-docs/gml-and-c-code/instances.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
