> 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/ru/skripting/entities-and-components.md).

# Объекты и компоненты

Игры All Out построены вокруг сущностей (объектов в мире) и компонентов (поведения/данных, прикреплённых к сущностям).

Если вы раньше работали с Unity: думайте «GameObject + Components». Если вы работали с Roblox: думайте «Instance + Scripts/Components». Основная идея та же: **вы создаёте игровой процесс, добавляя компоненты к сущностям.**

## Сущности

Сущности существуют в двух основных вариантах:

* **Размещены в редакторе**: они уже находятся в сцене при запуске.
* **Созданы во время выполнения**: вы создаёте их из скрипта.

### Создание и уничтожение сущностей

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

// Когда закончите:
entity.destroy();
```

{% hint style="warning" %}
При уничтожении сущности уничтожаются и её компоненты. Не сохраняйте ссылки на компоненты после уничтожения их сущности.
{% endhint %}

### Перебор сущностей

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

## Компоненты

Компоненты — это единицы поведения. Компонент «живет» на сущности и может читать/изменять эту сущность.

### Получение и добавление компонентов

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

player := entity.get_component(Player);

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

### Перебор компонентов

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

## Встроенные компоненты, которые вы будете часто использовать

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

// Необязательно: используйте пользовательский материал. Передайте true, если рендерер должен владеть им.
// sprite.set_material(material, true);
```

### Префабы (`Prefab_Asset`)

Префабы нужно создавать в редакторе. В скриптах вы их инстанцируете.

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

### Spine (`Spine_Animator`)

Если вы используете 2D-анимированных персонажей, вы часто будете работать с `Spine_Animator`. См. [Spine](/all-out-docs/ru/osnovnye-koncepcii-dvizhka/spine.md).

## Создание собственного компонента

Создавайте новые компоненты в отдельных файлах (например, `orbiter.csl`) и прикрепляйте их к сущностям либо:

* **Вручную в редакторе**, или
* **Во время выполнения** с `entity.add_component(...)`

Компоненты могут реализовывать колбэки жизненного цикла:

* `ao_start()`
* `ao_update(dt)`
* `ao_late_update(dt)` (после всех обновлений)
* `ao_end()` (при уничтожении)

Пример:

```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" %}
Методы жизненного цикла для глобальных скриптов (`ao_start`, `ao_update`, ...) описаны в [Жизненный цикл игры/кадра](/all-out-docs/ru/skripting/game-frame-lifecycle.md).
{% endhint %}

## Сериализуемые поля (`@ao_serialize`)

Используйте `@ao_serialize` чтобы отобразить поле в Inspector и включить его в сериализацию сцены и JSON.

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

## Триггеры и запросы близости

Коллайдеры-триггеры предоставляют `on_trigger_start`, `on_trigger_stay`, а `on_trigger_end` колбэки. См. [Навмеш и столкновения](/all-out-docs/ru/osnovnye-koncepcii-dvizhka/navmesh-and-collision.md) для настройки и сигнатур колбэков.

Используйте запросы близости, когда вам нужны все компоненты в радиусе или только ближайший.

Полезные вспомогательные функции:

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

Пример:

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

## Лучшие практики

* **Состояние на каждого игрока должно находиться в `Player`.** Избегайте глобальных переменных, которые сломаются при нескольких игроках.
* **Для поведенческой логики игрового процесса предпочитайте компоненты.** В итоге у вас получатся переиспользуемые фрагменты, которые можно прикреплять к разным сущностям.
* **Отрисовывайте UI игрока из `Player.ao_late_update`.** Оберните это в `is_local_or_server()`.
* **Используйте `is_local()` только для визуальных переопределений, специфичных для игрока.** Не изменяйте внутри него состояние игрового процесса или UI.
