Итак, я столкнулся с проблемой в игре, над которой я работаю, но она кажется довольно фундаментальной, которая, вероятно, возникает во многих играх.
Моя игра требует, чтобы во время анимации персонажа некоторые игровые функции выполнялись в определенный момент времени. И поэтому, как говорится в заголовке, мне интересно, каковы некоторые хорошие методы и фундаментальные стратегии для синхронизации связанных с игровым процессом событий / функций / действий с конкретными точками в анимации персонажа.
Вот несколько простых примеров того, о чем я говорю в различных типах игр:
Ваш персонаж перезаряжает свое оружие в шутере . Ваш персонаж воспроизводит анимацию «перезагрузки», но важно, чтобы функция, устанавливающая переменную currentAmmo, вызывалась только в тот момент, когда магазин был заменен, а пистолет взведен. Это может быть какой-то момент в середине анимации перезагрузки.
В пошаговой RPG ваши персонажи стоят в линии лицом к линии врагов. Когда приказано атаковать, один из ваших персонажей бежит / подпрыгивает к одному из врагов и рубит свой гигантский меч перед тем, как бежать / прыгать обратно на свое стоящее место. Вы хотите убедиться, что противник поврежден в тот момент, когда воспроизводится режущая анимация - какой-то момент между бегом и бегом назад.
В стелс-игре ваш персонаж может подкрасться и взаимодействовать с компьютерами и кнопками в мире. Может быть, есть кнопка, которая отключает подачу света на огни форпоста, который вы проникаете. Когда кнопка действия нажата, ваш персонаж протягивает руку и нажимает на кнопку, а затем возвращается в положение ожидания. Вы хотите, чтобы свет выключался в точной точке анимации push_button при нажатии кнопки.
По общему признанию, мой конкретный случай больше всего похож на второй пример , в котором я создал анимацию, в которой мой пошаговый персонаж выпадает вперед во время атаки, и я хочу, чтобы урон наносился в тот самый момент, когда анимация, кажется, вступает в контакт , Поскольку моя игра использует пошаговую систему (представьте что-то вроде Final Fantasy или Fire Emblem), я хочу урон / исцеление / магия / и т.д. быть примененным в правильное время во время каждой анимации персонажа, хотя я на самом деле не использую коллизии / хитбоксы.
Я должен упомянуть, что я делаю свою игру на популярном игровом движке, и что сейчас я обрабатываю это, используя их анимационные события или уведомления, чтобы достичь чего-то близкого к желаемым результатам - мой персонаж выполняет определенную команду и запускает анимация, специфичная для команды (то есть: 'attack_command'), и ресурсы анимации для каждой из моих команд должны включать в себя событие анимации / callback-вызов notify в функцию ExecuteCommand моих персонажей. Другими словами - персонаж говорит анимации атаки играть, а затем анимация атаки генерирует обратный вызов события / уведомления в персонаж в тот самый момент во время анимации, когда должен быть нанесен урон.
Честно говоря, пока это работает, но кажется, что это неправильно - как будто мне не хватает какой-то части общей картины! Одна из причин, по которой этот метод кажется неправильным, заключается в том, что он связывает игровую логику с активами анимации; если мой ресурс анимации забывает включить событие / обратный вызов ExecuteCommand (), команда не будет выполняться должным образом, и потребуется дополнительный код для проверки завершения анимации команды без ее выполнения. Это грязно, и это означает, что мой игровой процесс имеет странную зависимость от его активов. Конечно, я хочу, чтобы повреждение происходило в определенный момент во время моей анимации атаки, но я чувствую себя действительно странно из-за вызова кода геймплея внутри ресурсов анимации.
Так что я здесь пропускаю? Каковы некоторые хорошие общие методы для обработки подобных ситуаций, в которых вы хотите, чтобы определенные важные игровые действия происходили в определенное время во время анимации?
Изменить: Чтобы уточнить, это не вопрос, касающийся двигателя, и я не ищу конструкции / методы для конкретного двигателя. Меня интересуют общие методы синхронизации анимации / геймплея, которые можно использовать в ваших игровых проектах независимо от используемых технологий.
источник
Ответы:
Для синхронизации вам нужно решить, кто (ваш код, анимация или ни один из них) является органом синхронизации, «ритмом», под который «танцуют» все остальные.
Разные аранжировки подходят для разных игр:
Анимации - это источник времени (ваша текущая настройка)
Код игры может вызывать анимацию. Когда анимация достигает определенных точек, она вызывает события (например, перезагрузка выполнена), на которые может реагировать игровой код (например, сбрасывает доступные боеприпасы).
Если точное время анимации (независимо от состояния игры) является важной частью вашей игры, или вы специально хотите, чтобы ваши аниматоры контролировали время, рассмотрите этот подход.
Инструменты анимации Blender (3D) и Spine (2D) позволяют аниматору определять события, на которые может подписаться игровой код.
Код является временным органом
Обратное из вышеперечисленного: события, происходящие в игровом мире (например, игрок, решивший перезарядить свое оружие), приводят к запуску анимации и передаче параметров (например, времени до завершения перезагрузки). Каждая анимация использует предоставленные параметры, чтобы изменить ее внешний вид (например, запустить анимацию с соответствующей скоростью, чтобы «заданная часть» появлялась, когда она указана).
Анимации могут также прослушивать игровые события (например, игрок отменяет перезагрузку или приседает игрок во время перезагрузки) и соответствующим образом изменять их внешний вид.
Если ваша анимация может позволить себе проявлять гибкость в отношении времени, ваша игра в значительной степени зависит от процедурно сгенерированного контента, или вы специально хотите, чтобы ваши программисты контролировали время, рассмотрите этот подход.
Анимация персонажей Overgrowth в значительной степени структурирована таким образом: Дэвид Розен объясняет это в своем выступлении на GDC 14 (см., В частности,сегменты« Движение и продолжение» ).
Неявные сроки (внешние полномочия)
В ритм-играх или в других ситуациях, когда время контролируется внешним источником (в ритм-играх - ритм музыкальной дорожки), может иметь смысл моделировать вещи как таковые. Код и анимация игры могут одновременно считывать глобальную метку времени и состояние игры, а затем вести себя соответствующим образом, не связываясь друг с другом.
Если ваше игровое состояние и анимация в значительной степени зависят от внешнего источника синхронизации, рассмотрите этот подход.
Конечно, вы можете использовать разные подходы для разных систем в вашей игре. (Например, ритм-игры часто используют ритм песни в качестве внешнего авторитета, но анимации по-прежнему прослушивают события взаимодействия с игроком для отмены или изменения вида удерживаемых нот.)
источник
Я где-то читал, что почти все вычислительные проблемы могут быть решены с помощью дополнительного уровня абстракции, и я не вижу, чтобы ваш случай был другим.
Для этого требования я обычно вижу слой для контроля состояния персонажа. Таким образом, у персонажа будет текущая анимация и текущее состояние. Каждый со своей ответственностью.
Анимация отвечает только за визуальные эффекты, а состояние обрабатывает игровую логику для этого действия.
В моей файтинге состояние - это объект, который наследуется от класса BaseState и имеет метод Update (). Каждый персонаж имеет набор состояний, но одновременно может быть назначено только одно. И метод Update () текущего состояния вызывается один раз за кадр.
Он находится внутри функции Update (), в которой я выполняю всю эту логику: устанавливаю скорость персонажа в определенном кадре, увеличивает / уменьшает здоровье и т. Д.
источник