For the complete documentation index, see llms.txt. This page is also available as Markdown.

Анимации Spine

Вы можете добавлять в игру анимированные интерактивные объекты, используя нашу библиотеку из более чем 50 000 ригов Spine.

Spine — это механизм, на котором в All Out работают анимированные персонажи и объекты (сундуки, животные, декорации, VFX-риги и игрок).

Чтобы Spine казался проще, держите в голове такую модель:

  • Риг Spine (.spine): «чертёж» (кости + имена анимаций + имена скинов)

  • Spine_Animator: компонент на сущности, который отображает/обновляет риг Spine в мире

  • Spine_Instance: самостоятельный (не-компонентный) экземпляр — используется для анимаций UI или ручного управления временем жизни

  • Скины: «образы/варианты», которые определяют, какие изображения видны

  • Анимации: именованные таймлайны (например, "idle", "walk", "open")

Когда использовать Spine_Animator по сравнению с Spine_Instance

  • Используйте Spine_Animator для всего, что существует в мире (декораций, NPC, интерактивных объектов).

  • Используйте Spine_Instance напрямую, когда хотите отрисовать Spine в UI или вам нужен ручной контроль времени жизни.

Движок обновляет Spine_Animator автоматически. Самостоятельный экземпляр должен обновляться и уничтожаться вашим кодом.

Справочник по API Spine (CSL)

// Компонент — прикрепляется к сущностям в мире
Spine_Animator :: class : Component {
    depth_offset: float;
    layer: s32;
    mask_in_shadow: bool;
    instance: Spine_Instance #read_only;

    // Визуальные параметры
    color_multiplier: v4;
    scale: v2;
    speed_multiplier: float;
    state_machine: State_Machine #read_only;

    set_skeleton :: method(asset: Spine_Asset) -> u64;
    get_skeleton :: method(id: u64 = 0) -> Spine_Asset;
    set_animation :: method(animation: string, loop: bool, track: s64, speed: float = 1);

    // Скины
    set_skin          :: method(skin: string);
    enable_skin       :: method(skin: string);
    disable_skin      :: method(skin: string);
    disable_all_skins :: method();
    refresh_skins     :: method();
    get_skins         :: method() -> []string;
    set_to_setup_pose :: method();

    // Локальные смещения костей (для продвинутых)
    get_bone_local_position :: method(bone_name: string) -> v2;
    set_bone_local_position :: method(bone_name: string, position: v2);

    // Необязательно: управлять анимациями через конечный автомат
    set_state_machine       :: method(machine: State_Machine, transfer_ownership: bool);
    set_color_replace_color :: method(color: Color_Replace_Color);
    set_material            :: method(material: Material, transfer_ownership: bool);
    get_tint                :: method() -> v4;
    set_tint                :: method(tint: v4);
    set_destroy_entity_when_done_current_animation :: method(enabled: bool);
}

Spine_Animator наследует Component.awaken(). Когда ваш скрипт и аниматор запускаются на одной сущности, вызовите awaken() до обращения к экземпляру аниматора.

Добавление анимированных объектов в ваш мир

Есть 3 способа добавить анимированные объекты в вашу сцену, и все они создадут компонент Spine_Animator.

  • Перетащите любой анимированный ресурс из Каталог ассетов в вашу сцену

  • Создайте новую сущность и добавьте компонент Spine_Animator

    • Укажите поле Skeleton Data Asset на .spine-файл в ваших ресурсах

  • Добавьте аниматор Spine в ваш мир с помощью скрипта (это показано в примерах)

Если ваш код и Spine_Animator находятся на одной сущности и запускаются одновременно, вызовите spine.awaken() до вызова любых методов анимации.

Примеры

Открываемый сундук

Интерактивный сундук, который проигрывает анимацию «open», а затем остаётся открытым:

Имена анимаций и скинов должны совпадать с именами в риге.

Ходящая курица

Простой цикл «idle vs walk» на основе движения:

Управляемая машина

Если вам нужно поведение "driveable", самый простой подход — управлять движением с помощью собственной игровой логики и управлять анимацией в зависимости от того, движется ли машина.

Если вы переключаетесь только между двумя зацикленными анимациями, прямые set_animation вызовы обычно проще, чем построение конечного автомата.

Скины (варианты/образы)

Некоторые Spine не начинают скином по умолчанию. Если ваша сущность "невидима", вам, скорее всего, нужно выбрать скин.

События анимации

Используйте callback-функции, когда событие таймлайна Spine должно запускать геймплей или звук. Для Spine_Animator компонента регистрируйте callback'и на его экземпляре.

Callback события выполняется в общем предсказанном пути. Вызывайте геймплей и SFX напрямую; не оборачивайте это в Game.is_server() или is_local().

Самостоятельные экземпляры и UI.spine

Самостоятельный API предоставляет ручное управление временем жизни и обновлением анимации:

Храните экземпляр в постоянном состоянии UI игрока. Создайте его один раз, обновляйте и отрисовывайте его из ao_late_update, затем уничтожайте его из ao_end:

Не создавайте экземпляр внутри ao_late_update; иначе анимация будет перезапускаться каждый кадр, а предыдущий экземпляр будет утекать.

Конечные автоматы (необязательно, для сложной логики анимаций)

Вы можете упростить логику анимаций, вызывая set_animation напрямую. Если у вас много состояний (idle/run/attack/hit/death), State_Machine помогает один раз задать переходы, а затем просто устанавливать переменные/триггеры.

Ключевая идея: имена состояний должны совпадать с именами анимаций в вашем файле Spine.

Что делает конечный автомат

Представьте конечный автомат как небольшой «контроллер анимации»:

  • Вы задаёте состояния (имя каждого состояния должно совпадать с именем анимации Spine)

  • Вы задаёте переменные (bool, триггер, int, float)

  • Вы задаёте переходы между состояниями на основе этих переменных

  • Во время работы вы просто обновляете переменные (конечный автомат выбирает анимацию)

Минимальный пример: idle/walk + триггер атаки

Если вы передаёте transfer_ownership = true в set_state_machine, аниматор сам уничтожит конечный автомат за вас. Иначе вы должны уничтожить его сами.

Поиск и устранение неполадок

В: Я перетащил spine-ресурс в сцену, и не вижу никакого объекта — это просто пустая сущность

О: Нажмите "Add Skin" и выберите вариант Spine, который нужно применить! У некоторых Spine нет скина по умолчанию.

В: Мой скрипт падает, когда я вызываю методы анимации у моего Spine_Animator

О: Если ваш скрипт и Spine_Animator запускаются одновременно, вызовите spine.awaken() до вызова любых методов анимации.

В: Я изменил скины, но ничего не произошло

О: После любого изменения скина (set_skin, enable_skin, disable_skin, disable_all_skins), вы должны вызвать refresh_skins().

Пользовательские скины/анимации игрока

Если вы хотите добавить собственные анимации своему игроку, вы можете сделать это, объединив базовый риг Spine игрока All Out с пользовательским ригом, содержащим дополнительные анимации. Мы можем предоставить много таких; просто Поддержка разработчиков.

Формат рига Spine

Риги Spine включают:

  • Файл скелета (.spine) с костями, скинами, анимациями и структурой.

  • Файл атласа (.atlas), который сопоставляет attachment'и с изображениями.

  • Каждая страница изображения, указанная в атласе. Обычно экспорт на одну страницу имеет один .png.

Создание собственных анимаций

Формат экспорта

Чтобы использовать пользовательский риг Spine в All Out, экспортируйте стандартный пакет Spine в вашу res папку:

  • something.spine

  • something.atlas

  • Каждый файл изображения, названный по something.atlas

Если вы не уверены в настройках экспорта, начните с существующего ресурса All Out Spine из Asset Catalog и повторите его структуру или свяжитесь с нами!

Последнее обновление