> 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/all-out-docs/docs-es/programacion/entities-and-components.md).

# Entidades y componentes

Los juegos de All Out se construyen alrededor de entidades (cosas en el mundo) y componentes (comportamiento/datos adjuntos a las entidades).

Si has usado Unity antes: piensa “GameObject + Components”. Si has usado Roblox: piensa “Instance + Scripts/Components”. La idea central es la misma: **compone la jugabilidad añadiendo componentes a las entidades.**

## Entidades

Las entidades existen de dos formas comunes:

* **Colocadas en el editor**: ya están en la escena al iniciar.
* **Creadas en tiempo de ejecución**: las generas desde un script.

### Creación y destrucción de entidades

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

// Cuando termines:
entity.destroy();
```

{% hint style="warning" %}
Destruir una entidad también destruye sus componentes. No conserves referencias a los componentes después de destruir su entidad.
{% endhint %}

### Iterar sobre entidades

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

## Componentes

Los componentes son las unidades de comportamiento. Un componente “vive en” una entidad y puede leer/modificar esa entidad.

### Obtener y añadir componentes

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

player := entity.get_component(Player);

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

### Iterar sobre componentes

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

## Componentes integrados que usarás mucho

### `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;

// Opcional: usa un material personalizado. Pasa true si el renderizador debe ser su propietario.
// sprite.set_material(material, true);
```

### Prefabs (`Prefab_Asset`)

Los prefabs deben crearse en el editor. En los scripts, los instancias.

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

### Spine (`Spine_Animator`)

Si usas personajes animados en 2D, a menudo trabajarás con `Spine_Animator`. Consulta [Spine](/all-out-docs/docs-es/conceptos-basicos-del-motor/spine.md).

## Escribir un componente personalizado

Crea nuevos componentes en archivos dedicados (p. ej., `orbiter.csl`) y adjúntalos a entidades de cualquiera de estas formas:

* **Manualmente en el editor**, o
* **En tiempo de ejecución** con `entity.add_component(...)`

Los componentes pueden implementar callbacks del ciclo de vida:

* `ao_start()`
* `ao_update(dt)`
* `ao_late_update(dt)` (después de todas las actualizaciones)
* `ao_end()` (al destruirse)

Ejemplo:

```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" %}
Los métodos del ciclo de vida para scripts globales (`ao_start`, `ao_update`, ...) se tratan en [Ciclo de vida del juego/fotograma](/all-out-docs/docs-es/programacion/game-frame-lifecycle.md).
{% endhint %}

## Campos serializados (`@ao_serialize`)

Usa `@ao_serialize` para exponer un campo en el Inspector e incluirlo en la serialización de la escena y de JSON.

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

## Triggers y consultas de proximidad

Los colliders trigger exponen `on_trigger_start`, `on_trigger_stay`, y `on_trigger_end` callbacks. Consulta [Navmesh y colisión](/all-out-docs/docs-es/conceptos-basicos-del-motor/navmesh-and-collision.md) para la configuración y las firmas de los callbacks.

Usa consultas de proximidad cuando necesites todos los componentes dentro de un radio o solo el más cercano.

Ayudas útiles:

```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
```

Ejemplo:

```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 {
    // ...
}
```

## Buenas prácticas

* **El estado por jugador debe estar en `Player`.** Evita variables globales que fallarían con varios jugadores.
* **Prefiere componentes para los comportamientos de jugabilidad.** Acabarás con piezas reutilizables que puedes adjuntar a distintas entidades.
* **Dibuja la interfaz del jugador desde `Player.ao_late_update`.** Envuélvelo en `is_local_or_server()`.
* **Usa `is_local()` solo para invalidaciones visuales específicas del jugador.** No cambies el estado de jugabilidad ni de la UI dentro de él.
