Я довольно новичок в разработке игр (но не в программировании), и я пытаюсь выяснить, что было бы лучшим способом справиться с коммуникацией между мирами. Я имею в виду следующее:
Я читал о системах компонентов сущностей (ECS) и о том, как люди предлагают использовать разные миры / пространства ( http://gamedevelopment.tutsplus.com/tutorials/spaces-useful-game-object-containers--gamedev-14091 ) для подраздел игры. Например, HUD, инвентарь или бой / движение каждый получает отдельный мир / пространство (потому что они имеют различную графику и основную логику.
Однако мне было интересно, как инвентарь или HUD узнают о здоровье игрока, когда здоровье обрабатывается в другом пространстве / мире, например, в бою?
Это также относится к ходу игры в целом, например, к диалогу с NPC (диалог будет отдельным пространством, так как это всплывающий экран), но как вы будете передавать выбор, сделанный в (или состоянии) диалога, в другие пространства / миры? , Или в основном любые другие типы событий, которые влияют на ход игры в разных пространствах / мирах (здоровье, мана, квесты, диалог, бой, инвентарь, хад и т. Д.)
Как справиться с таким дизайном? Нужен ли ему (в реализации) одноэлементный объект, который содержит всю эту информацию? Это было бы странно, потому что тогда components
нужно было передавать каждое изменение этому одноэлементному объекту, который ощущается как выполнение действий дважды (в отличие от основной СУХОЙ программирования) ...
Я немного растерялся с точки зрения дизайна, какие-нибудь указатели?
---РЕДАКТИРОВАТЬ---
Поэтому я прочитал несколько других постов, предложенных в комментариях, и получил общее представление о возможностях, однако у каждого из них, похоже, есть один существенный недостаток, который делает их просто неправильными. Вполне возможно, что я наблюдаю за деталями, которые могут решить эти недостатки, поэтому не стесняйтесь поправлять меня. Я постараюсь дать обзор, а также некоторые ответы на некоторые вопросы.
Я вижу три основных варианта «обмена» данными между пробелами. Хотя большинство сообщений посвящено обмену данными между системами, я чувствую, что то же самое можно применить к обмену данными между системами.
1. Запросы
Пример : если мир HUD должен знать текущее здоровье игрока, он может запросить другой мир и запросить текущее здоровье.
Недостаток : Миры должны знать друг о друге, что является основной проблемой зависимости и противоречит разделению.
2: Прямой обмен сообщениями (синхронизация и асинхронность)
Пример : если во время боя здоровье игрока меняется, он может отправлять сообщения (синхронизация и асинхронность, что угодно) в другие миры, которым необходимо знать об этом изменении.
Недостаток : все еще проблема развязки: миры должны знать друг о друге.
3: косвенный обмен сообщениями (синхронизация и асинхронность) <- лучший вариант
Пример : если во время боя здоровье игрока меняется, он может отправлять сообщения (синхронизация и асинхронность, что угодно) в общий центр сообщений. Другие миры / системы, которым необходимо знать об этом изменении, подписываются на определенный канал сообщений и читают сообщения.
Верх : полностью отделен, легко управляемый и расширяемый.
Недостаток / неясность : когда канал сообщений узнает, что сообщения должны быть удалены? Или, может быть, система, на которую подписаны, помечает (только для себя) сообщение как прочитанное и ожидает новых сообщений -> окно сообщений через некоторое время становится огромным. Как миры / системы обрабатывают порядок? Например, во время кадра: если HUD уже опрашивал сообщение о работоспособности и после этого состояние меняется, следующий кадр HUD обновляется. Для некоторых приложений это может быть неправильным способом.
Q: один игровой объект может существовать в нескольких местах
Я использую Artemis ECS Framework, который поставляется со встроенными пробелами (называемыми мирами). Каждая сущность (и вместе с ней данные в форме компонентов) создаются в мире и поэтому не могут быть разделены между мирами.
Ответы:
Один из способов взглянуть на это состоит в том, что вы, возможно, вкладываете слишком много в свои игровые объекты.
Нет причины, по которой код, который фактически подключает HUD к вашей игре в мире, должен находиться в компоненте / системе, которая живет в каком-то определенном пространстве. Этот код, возможно, будет лучше жить в центральном менеджере или глобальном скрипте, который имеет доступ ко всем пространствам и всем объектам, и затем может взаимодействовать с кодом, который знает, когда на самом деле создать пространство и что в него вставить (например, код который порождает игрока, сохраняет его состояние между уровнями и т. д.).
Вы также можете просто иметь «главное пространство», которое содержит игровые объекты с логикой или данными, которые должны сохраняться в прошлом или манипулировать пространствами, используемыми для уровней и пользовательского интерфейса. Этот подход распространен в механизмах, которые вынуждают разработчиков размещать все сценарии / логику на компонентах / объектах (например, в Unity вы создадите глобальный объект Main и сохраните его при выгрузке сцены; если Unity действительно имеет пробелы, вы ' буду использовать их вместо флага).
Помните, что злоупотребление вашей ECS - это то же самое, что злоупотребление шаблонами проектирования; просто потому, что у вас есть отличный новый инструмент, не означает, что вы должны использовать его для решения всех проблем, с которыми вы сталкиваетесь. Оцените свое проблемное пространство и выберите наиболее подходящее решение, даже если это старые грязные вещи, которые ваши предки использовали еще в темные века 90-х годов. :п
источник
Я создал несколько прототипов, но не слишком большой, и для обработки нескольких пространств я просто создал игровой объект, содержащий мир, игрока и т. Д., А затем я настроил некоторые свойства, которые требуются для некоторых других пространств, например, для здоровья. , в игровом объекте
Всякий раз, когда он вызывается, вы получаете здоровье игрока. таким образом, я мог бы отправить его в HUD и отобразить панель здоровья.
Он не самый чистый, но он выполняет свою работу, я провел некоторое тестирование производительности еще в 2013 году, и все, казалось, работало гладко. Чтобы избежать таких зависимостей, вы всегда можете сбросить планку здоровья, когда здоровье игрока равно нулю.
Обычно, когда игрок не существует, это означает, что пользователь находится либо в меню, либо в вырезке.
Пример кода:
Надеюсь, это то, что вы искали.
источник
Над этим я работаю последние пару недель. Я работаю над своей собственной библиотекой ECS (хотел сделать это для опыта и просто попробовать, потому что я хотел сделать это в течение достаточно долгого времени).
Это ссылка на github: https://github.com/gioragutt/xna-ecs
Для вашей проблемы я всегда писал небольшую библиотеку pubsub, которую вы можете увидеть здесь
По сути, у меня есть
EmsClient
класс, из которого можно извлечь материал. В настоящее время мои компоненты не делают этого, но классы более высокого уровня, хотя нет причин не делать этого. Я подписываюсь имена сообщений, а также обеспечить обратный вызов со следующей подписью:Action<JObject>
. Как вы уже поняли, я использую Json Objects как средство для передачи сообщений. Я сделал это после того, как раньше использовал justbyte[]
's, и обнаружил, что мне нужно что-то более общее, и поскольку я привык к чему-то подобному на своем рабочем месте (у нас есть IPCD, который работает аналогично, за исключением обратного вызова метод всегда один и тот же, так как обычно мы разделяем ответственность между разными обработчиками).Существует
EmsServer
(один на сервере и один на каждом клиенте), который отвечает за перемещение сообщений междуEmsClient
ними в своей области (EmsServer
на стороне сервера перемещение сообщений междуEmsClients
на стороне сервера, и наоборот на стороне клиента).Для обмена сообщений между клиентом и сервером, я создал ,
EmsServerEndpoint
который являетсяEmsClient
самим, он просто не логика буферизации отправленных сообщений на этом царстве, и промывке их в другие сферы (FE клиент посылает сообщение сервера, в то время как при сервер передает каждое сообщение всем подключенным клиентам.Вы можете увидеть использование в большом количестве мест, ф:
ClientGameManager
,ServerGameManager
.В то время как, для примера, если я хочу , чтобы добавить компонент графического интерфейса для игрока, вы можете посмотреть ЗДЕСЬ , на
BeginAllocateLocal
иBeginAllocateRemote
методы, которые отвечают за строительствоGameObjects
игроков. КаждыйGameObject
содержитEntity
(из библиотеки ECS) и anIComponentContainer
(что тоже из библиотеки ECS). КаждыйGameObject
автоматически получает преобразование (как вUnity
, из которого я взял вдохновение).Мой код в значительной степени говорит сам за себя, и если вы доберетесь до него, я ищу критику за него, поэтому я хотел бы конструктивной критики :)
Надеюсь, что мой код поможет вам с некоторыми идеями!
источник
Рассмотрите компоненты шаблона наблюдателя / субъекта для ваших игровых компонентов и компонентов пользовательского интерфейса. Вы соединяете их вместе при создании / загрузке, а затем забываете о них. Если здоровье персонажа меняется, он уведомляет всех наблюдателей, которые могут делать с информацией все, что они захотят.
источник