> For the complete documentation index, see [llms.txt](https://docs.allout.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.allout.game/scripting/entities-and-components.md).

# Entities and Components

All Out games are built around entities (things in the world) and components (behavior/data attached to entities).

If you’ve used Unity before: think “GameObject + Components”. If you’ve used Roblox: think “Instance + Scripts/Components”. The core idea is the same: **you compose gameplay by adding components to entities.**

## Entities

Entities exist in two common ways:

* **Placed in the editor**: they’re already in the scene at startup.
* **Created at runtime**: you spawn them from script.

### Creating and destroying entities

```go
entity := Scene.create_entity();
entity.set_local_position({10, 20});
entity.set_local_scale({2.5, 2.5});
entity.set_local_rotation(0);

// When you're done:
entity.destroy();
```

{% hint style="warning" %}
Destroying an entity destroys its components too. Don’t keep references to components after you destroy their entity.
{% endhint %}

### Iterating entities

```go
for e: entity_iterator() {
    // ...
}
```

## Components

Components are the units of behavior. A component “lives on” an entity and can read/modify that entity.

### Getting and adding components

```go
sprite := entity.get_component(Sprite_Renderer);

player := entity.get_component(Player);

my_comp := entity.add_component(My_Component);
```

### Iterating components

```go
for enemy: component_iterator(Enemy) {
    enemy.tick_ai();
}
```

## Built-in components you’ll use a lot

### `Sprite_Renderer`

```go
texture := get_asset(Texture_Asset, "ui/button.png");

sprite := entity.get_component(Sprite_Renderer);
sprite.set_texture(texture);
sprite.color = {1, 1, 1, 1}; // RGBA
sprite.depth_offset = 0.5;
sprite.layer = 10;

// Optional: use a custom material. Pass true if the renderer should own it.
// sprite.set_material(material, true);
```

### Prefabs (`Prefab_Asset`)

Prefabs must be created in the editor. In scripts, you instantiate them.

```go
prefab := get_asset(Prefab_Asset, "MyPrefab.prefab");
spawned := instantiate(prefab);
spawned.set_local_position({1, 3});
```

### Spine (`Spine_Animator`)

If you’re using 2D animated characters, you’ll often work with `Spine_Animator`. See [Spine](/core-engine-concepts/spine.md).

## Writing a custom component

Make new components in dedicated files (e.g. `orbiter.csl`) and attach them to entities either:

* **Manually in the editor**, or
* **At runtime** with `entity.add_component(...)`

Components can implement lifecycle callbacks:

* `ao_start()`
* `ao_update(dt)`
* `ao_late_update(dt)` (after all updates)
* `ao_end()` (when destroyed)

Example:

```go
Orbiter :: class : Component {
    center: v2;
    radius: float;
    speed: float;
    angle: float;

    ao_start :: method() {
        center = entity.local_position;
        radius = 2;
        speed = 1;
        angle = 0;
    }

    ao_update :: method(dt: float) {
        angle += speed * dt;

        offset_x := cos(angle) * radius;
        offset_y := sin(angle) * radius;

        entity.set_local_position({center.x + offset_x, center.y + offset_y});
    }
}
```

{% hint style="info" %}
Lifecycle methods for global scripts (`ao_start`, `ao_update`, ...) are covered in [Game/Frame Lifecycle](/scripting/game-frame-lifecycle.md).
{% endhint %}

## Serialized fields (`@ao_serialize`)

Use `@ao_serialize` to expose a field in the editor (and often to enable saving/persistence where applicable).

```go
Chest :: class : Component {
    capacity: int @ao_serialize;
}
```

## Finding nearby components (proximity queries)

CSL does not have collision callbacks. A common pattern is “query nearby components and check distance”.

Useful helpers:

```go
Scene.get_all_components_in_range     :: proc(position: v2, range: float, results: ref [..]$T)
Scene.get_closest_component_in_range  :: proc(position: v2, range: float, $T: typeid) -> T, bool
```

Example:

```go
nearby: [..]Enemy;
Scene.get_all_components_in_range(player.entity.world_position, 5.0, ref nearby);

for e: nearby {
    // ...
}

closest_pickup, found := Scene.get_closest_component_in_range(player.entity.world_position, 2.0, Pickup);
if found {
    // ...
}
```

## Best practices

* **Per-player state belongs on `Player`.** Avoid global variables that would break with multiple players.
* **Prefer components for gameplay behaviors.** You’ll end up with reusable pieces you can attach to different entities.
* **Keep cosmetic work local.** UI/particles should usually run behind `is_local()` checks.


---

# 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://docs.allout.game/scripting/entities-and-components.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.
