Я разработал систему сущностей для FPS. Это в основном работает так:
У нас есть «мир» -объект, называемый GameWorld. Он содержит массив GameObject, а также массив ComponentManager.
GameObject содержит массив Component. Он также предоставляет механизм событий, который действительно прост. Сами компоненты могут отправлять событие объекту, которое передается всем компонентам.
Компонент - это то, что придает GameObject определенные свойства, и, поскольку GameObject на самом деле является их контейнером, все, что связано с игровым объектом, происходит в Компонентах. Примеры включают ViewComponent, PhysicsComponent и LogicComponent. Если связь между ними необходима, это можно сделать с помощью событий.
ComponentManager просто интерфейс, такой же как Component, и для каждого класса Component, как правило, должен быть один класс ComponentManager. Эти менеджеры компонентов отвечают за создание компонентов и их инициализацию со свойствами, считанными из чего-то вроде XML-файла.
ComponentManager также заботится о массовых обновлениях компонентов, таких как PhysicsComponent, где я буду использовать внешнюю библиотеку (которая делает все в мире одновременно).
Для настройки я буду использовать фабрику для сущностей, которая будет читать либо XML-файл, либо скрипт, создавать компоненты, указанные в файле (который также добавляет ссылку на него в правильном диспетчере компонентов для массовых обновлений), и затем вставьте их в объект GameObject.
Теперь возникает моя проблема: я собираюсь попытаться использовать это для многопользовательских игр. Я понятия не имею, как подойти к этому.
Во-первых: какие объекты должны быть у клиентов с самого начала? Я должен начать с объяснения того, как движок для одного игрока будет определять, какие объекты создавать.
В редакторе уровней вы можете создавать «кисти» и «сущности». Щетки предназначены для таких вещей, как стены, полы и потолки, в основном простых форм. Сущности - это GameObject, о котором я вам говорил. При создании сущностей в редакторе уровней вы можете указать свойства для каждого из его компонентов. Эти свойства передаются непосредственно какому-либо конструктору в скрипте объекта.
Когда вы сохраняете уровень для загрузки движка, он раскладывается на список сущностей и связанных с ними свойств. Кисти превращаются в сущность "мировое возрождение".
Когда вы загружаете этот уровень, он просто создает все сущности. Звучит просто, а?
Теперь, когда я сталкиваюсь с существами, у меня возникают многочисленные проблемы. Во-первых, какие сущности должны существовать на клиенте с самого начала? Предполагая, что и сервер, и клиент имеют файл уровня, клиент может также создать все объекты уровня, даже если они существуют только для целей правил игры на сервере.
Другая возможность состоит в том, что клиент создает объект, как только сервер отправляет информацию о нем, и это означает, что у клиента будут только те объекты, которые ему нужны.
Другой вопрос, как отправить информацию. Я думаю, что сервер может использовать дельта-сжатие, что означает, что он отправляет новую информацию только тогда, когда что-то меняется, а не отправляет снимок клиенту при каждом кадре. Хотя это означает, что сервер должен отслеживать, что каждый клиент знает в данный момент.
И, наконец, как сеть должна быть введена в двигатель? Я имею в виду компонент NetworkComponent, который внедряется в каждую сущность, которая должна быть подключена к сети. Но как сетевой компонент должен знать, какие переменные должны быть в сети, и как получить к ним доступ, и, наконец, как соответствующий сетевой компонент на клиенте должен знать, как изменять сетевые переменные?
У меня огромные проблемы с приближением к этому. Я был бы очень признателен, если бы вы помогли мне в пути. Я открыт для советов о том, как улучшить дизайн системы компонентов, так что не бойтесь предлагать это.
источник
Собирался написать комментарий, но решил, что это может быть достаточно информации для ответа.
Во-первых, +1 за такой хорошо написанный вопрос с тоннами деталей, по которым можно судить об ответе.
Для загрузки данных я бы попросил клиента загрузить файл world из мира. Если у ваших сущностей есть идентификаторы, которые берутся из файла данных, тогда я бы также загрузил их по умолчанию, чтобы ваша сетевая система могла просто ссылаться на них, чтобы узнать, о каких объектах идет речь. Каждый, кто загружает одни и те же исходные данные, должен иметь в виду, что все они имеют одинаковые идентификаторы для этих объектов.
Во-вторых, не создавайте компонент NetworkComponent, так как он будет делать только репликацию данных в других существующих компонентах (физика, анимация и т. П. - некоторые общие вещи для отправки). Чтобы использовать собственное наименование, вы можете создать NetworkComponentManager. Это будет немного отличаться от других ваших отношений между Component и ComponentManager, но это может быть реализовано, когда вы запускаете сетевую игру, и компоненты любого типа, имеющие сетевой аспект, передают свои данные менеджеру, чтобы он мог их упаковать. и отправь это. Это где ваши функции сохранения / загрузки могут быть использованы, если у вас есть какой-то механизм сериализации / десериализации, который вы также можете использовать для упаковки данных, как уже упоминалось,
Учитывая ваш вопрос и уровень информации, я не думаю, что мне нужно вдаваться в подробности, но если что-то не ясно, пожалуйста, оставьте комментарий, и я обновлю ответ, чтобы решить эту проблему.
Надеюсь это поможет.
источник