Мой вопрос:
Как я могу обрабатывать игровые состояния в моей системе сущностей, не прибегая к хранению стека игровых состояний?
Таким образом, проект моей системы сущностей означает, что когда сущность должна регистрироваться, например, для событий ввода, компонент ввода вызывает систему ввода и говорит «зарегистрировать эту сущность для этого ввода». Это все хорошо и хорошо, однако, если вы добавите в это понятие игровых состояний (скажем, экран паузы), станет проблемой решить, находится ли сущность в текущем состоянии и должна получить ввод.
Я мог бы дополнить компонент / систему ввода так, чтобы он сказал: «зарегистрируйте эту сущность для этого ввода, находясь в этих состояниях игры», но для этого необходимо, чтобы каждая сущность знала, в каких состояниях она будет использоваться, а это может быть неочевидным. Кроме того, сохранение списка игровых состояний вокруг каждого зарегистрированного входа (и других систем, которые используют обратные вызовы) не кажется слишком эффективным.
Еще одна идея, которая у меня возникла, заключается в том, что будет существовать объект, представляющий игровое состояние, пометить его как отключенный, а затем при генерации входного события проверить, что объект не является потомком отключенного объекта игрового состояния. Кажется, дорого отрабатывать родителя для каждого обратного вызова.
Другая идея состоит в том, чтобы все системы хранили свои данные, привязанные к текущему состоянию, чтобы при создании ввода целевой объект даже не был кандидатом. Однако это действительно вредит способности разрешать связь между сущностями в разных состояниях (не такая уж большая проблема для экранов паузы, но подумайте о взломе замков в Oblivion / Skyrim).
Единственная другая идея, которая у меня возникла, - это заставить все компоненты обрабатывать события изменения состояния и связываться с их соответствующей системой, чтобы отключить все, что они зарегистрировали, и повторно включить его при переключении обратно в это состояние.
Второй (пометить объект как отключенный) и далее (каждый компонент имеет дело с изменениями состояния) кажутся лучшими из моих идей, но ни одна из них не вызывает у меня особого восхищения.
У кого-нибудь есть еще идеи, как это сделать?
редактировать Хотя я и говорю о вводе конкретно в этом вопросе, он может означать любую систему, способную отправлять сообщения / события объектам, такие как коллизии, события таймера и т. д.
источник
Ответы:
Часто используется промежуточное звено,
Intent System
которое абстрагирует ввод и отслеживает контекст и соответствующие игровые состояния.Система Intent прекращает передачу входных данных, например, когда симуляция приостановлена. Он также обрабатывает отображение между событиями контроллера и намерениями (движение в направлении, бег, стрельба, перезагрузка ...).
Таким образом, другие ваши компоненты не зависят от конкретных игровых планшетов / входов (BUTTON_A, BUTTON_B против BUTTON_X, BUTTON_O ...), но все они реагируют на одни и те же намерения (IntentRun, IntentReload ...).
Другое преимущество состоит в том, что система намерений может знать о добавлении / удалении доступных контроллеров, поскольку она может отправлять намерения любому подписчику даже вне симуляции, с которой вы можете справиться
AddPlayer(controllerID)
.Сколько информации о состоянии игры вы предоставляете системе либо через события / сообщения, либо напрямую от вас. Но время, потраченное на систему Intent, обычно того стоит.
Вы можете управлять контекстами намерений, которые будут генерировать намерения, когда они присоединены к системе.
Контекст может быть приоритетным, то есть:
Таким образом, вы можете добавлять и удалять контексты, которые в настоящее время актуальны.
И одна вещь о целых системах намерений состоит в том, что она должна работать, пока симуляция приостановлена.
Один из способов, который часто используется для воспроизведения / приостановки симуляции игры без прерывания обновлений, не связанных с симуляцией, - это использование разных наборов времени. то есть
GenericSystem::onTime(Long time, Long deltaTime, Long simTime, Long simDeltaTime)
.При таком подходе ваш движок может просто блокировать приращение игрового simTime, что, в свою очередь, блокирует обновления соответствующих анимационных и физических движков, которые используют
simTime and simDeltaTime
, позволяя непрерывно обновлять эффект пружины вашей камеры, если он должен двигаться даже во время паузы, анимации эффект загрузки виртуального внутриигрового билборда во время загрузки данных ...источник
Как насчет создания глобальной системы событий, а затем иметь компонент слушателя событий для каждой вашей сущности? После события «Изменение состояния игры» вы можете поиграть с компонентами индивидуально для каждой конкретной сущности.
Допустим, у вас есть компонент ввода. После того, как компонент прослушивателя событий получает событие изменения состояния игры, он меняет очень специфические значения для этого конкретного компонента ввода, поэтому он не будет принимать никаких входных вызовов или не будет совершать какие-либо движения или ответные вызовы системе или ее владельцу.
Это работает для меня, так как большинство моих компонентов написаны на скрипте (через Lua). Т.е. у меня есть компонент ввода, который запускается один раз при нажатии клавиши и запускает движение + направление, а затем срабатывает при отпускании клавиши и срабатывает стоп + направление. Существует также компонент прослушивателя событий, который связывается с компонентом ввода (если игра приостановлена), чтобы прекратить выполнение любой функции и остановить при необходимости. Я мог бы легко добавить другой объект с другой реакцией на те же события и нажатия клавиш, используя другой скрипт. Таким образом, вы можете сохранить взаимодействие между различными объектами в разных состояниях и даже сделать его гораздо более настраиваемым. Более того, некоторые объекты могут даже не иметь компонента слушателя событий.
То, что я только что объяснил, является практическим примером вашего четвертого решения.
источник