Я довольно новичок в идее систем сущностей, прочитав кучу вещей (наиболее полезно, этот отличный блог и этот ответ ).
Хотя у меня возникли небольшие проблемы с пониманием, как что-то столь же простое, как возможность манипулировать положением объекта с помощью неопределенного числа источников.
То есть у меня есть моя сущность, которая имеет компонент позиции. Затем в игре есть какое-то событие, которое сообщает этой сущности, чтобы она прошла определенное расстояние в данное время.
Эти события могут произойти в любое время и будут иметь разные значения для позиции и времени. В результате они будут составлены вместе.
В традиционном ОО-решении у меня был бы какой-то MoveBy
класс, который содержит расстояние / время и массив из них внутри моего класса игровых объектов. В каждом кадре я бы перебрал все MoveBy
и применил его к позиции. Если a MoveBy
достиг времени окончания, удалите его из массива.
С системой сущностей меня немного смущает то, как я должен воспроизводить такое поведение.
Если бы одновременно было только одно из них, вместо того, чтобы соединять их вместе, это было бы довольно просто (я считаю) и выглядело бы примерно так:
PositionComponent
содержащий x, y
MoveByComponent
содержащий x, y, time
Entity
который имеет как PositionComponent
иMoveByComponent
MoveBySystem
который ищет сущность с обоими этими компонентами и добавляет значение MoveByComponent
к PositionComponent
. Когда time
достигается, он удаляет компонент из этой сущности.
Я немного сбит с толку относительно того, как бы я делал то же самое со многими движениями.
Мои первоначальные мысли таковы:
PositionComponent
так MoveByComponent
же, как и выше
MoveByCollectionComponent
который содержит массив MoveByComponent
с
MoveByCollectionSystem
который ищет сущность с a PositionComponent
и a MoveByCollectionComponent
, перебирает MoveByComponent
s внутри него, применяя / удаляя при необходимости.
Я предполагаю, что это более общая проблема: иметь много одинаковых компонентов и хотеть, чтобы соответствующая система воздействовала на каждый. Мои сущности содержат свои компоненты внутри хеша типа компонента -> компонента, поэтому строго имеют только 1 компонент определенного типа для каждой сущности.
Это правильный способ смотреть на это?
Должна ли сущность иметь только один компонент данного типа за все время?
MoveBy
функциональность - это просто скорость? Похоже, вы на правильном пути. Что касается вашего второго вопроса, существует множество различных реализаций систем сущностей / компонентов. Описанный в моем ответе, который вы связали, будет иметь только один компонент данного типа.move x by 10 in 2 seconds
иmove x by -10 in 2 seconds
сущность будет стоять на месте?Ответы:
Для вашего сценария мы обычно добавляем три компонента к игровому объекту:
Когда игровые объекты нуждаются в некотором типе функций ИИ, таких как перемещение по пути, как вы описали, мы назначаем AIController для его списка компонентов. Контроллеры AIC на самом деле не более чем оболочка, которая шагает по Поведенческому Дереву. Дерево поведения - это то, где мы проектируем реальную функциональность, которую мы хотим, чтобы игровой объект выполнял, например:
Подсистема AI управляет контроллерами AIC, поэтому подсистема выбирает контроллер, который, в свою очередь, шагает по дереву поведения. MoveToNode () просматривает текущую позицию / ориентацию, вычисляет вектор направления и скорость, к которой вы хотите переместиться на основе аргументов конструктора, и устанавливает значения для компонента скорости. Система движения отвечает за чтение компонентов движения со значениями и применение физики, соответственно обновляя положение / ориентацию.
Приведенный выше код просто перемещает игровой объект из локации появления в x, y, z в мировом пространстве, затем ждет минимум 30 секунд, затем перемещает игровой объект в локации a, b, c и затем ждет еще 30 секунд. Как только ожидание закончено, последовательность действий завершена, поэтому она повторяется с самого начала.
Это позволяет вам легко определить, какие функциональные возможности AI вам нужны, и все это содержится в подсистеме AI с минимальным воздействием на вашу подсистему Entity. Это также позволяет вам поддерживать список компонентов вашей системы сущностей без особой детализации.
источник
Можно добавить контроллеры в свой дизайн. Объекты владеют данными для представления положения (в случае с моим двигателем у них есть данные, которые также запоминают предыдущие положения, поэтому я могу знать вектор скорости, а также, перемещаются ли они или телепортируются), но они ничего не знают о физике или AI. Контроллеры перемещают объекты, и вы можете иметь много контроллеров, влияющих на один и тот же объект, или один контроллер, влияющий на различные объекты.
Например: создайте базовый класс Controller с помощью метода run () или, если вам не нравится имя, вызовите think (), update () или tick (). Затем вы наследуете его и создаете MoveController, NPCController, PlayerInputController (для сущности игрока), PhysicController; Затем вы реализуете метод run (). Я бы поместил ваш MoveByComponent в MoveController, а не в Entity.
Эти контроллеры могут быть созданы каждым объектом, если они содержат данные, специфичные для объекта. Они могут быть уничтожены или сброшены для последующего использования. Также вы можете использовать контроллер для перемещения группы сущностей, например, в игре RTE, если вам нужно перемещать различные юниты как группу, если контроллер для каждого юнита может ухудшить производительность игры, тогда вы можете просто назначить все юниты в GroupController или LegionController и позволить ему перемещать единицы как часть организованной группы. В бою, если игра допускает поведение отдельных юнитов, и, вероятно, большинство игр делают это, вам придется переключиться на UnitController, но лучше делать это только тогда, когда это необходимо, чем с самого начала.
В моей развивающей игре у меня есть MoveController, который перемещает объекты по пути, один MoveController существует для каждого NPC и персонажа игрока. Иногда один создается для коробок или рок, которые игрок может толкнуть. PhysicController, только один экземпляр, который будет проверять позиции всех назначенных ему объектов, если какой-то объект сталкивается с другим назначенным объектом, вычисляется результирующая позиция обоих (на самом деле он делает больше, но вы понимаете). NPCController - это ИИ, один экземпляр на каждого NPC. Он проверяет ситуацию с NPC и решает, куда двигаться, а затем указывает путь к MoveController, который фактически перемещает NPC. Контроллеры имеют приоритет, поэтому я могу заранее определить их порядок, PhysicController выполняется последним.
Я выступаю за контроллеров, но это не единственный «правильный» вариант. Например, я помню интерфейс Entity в движке Cafu, который имеет метод think () в самом Entity, пользователь класса должен наследовать от Entity и реализовывать think (), я помню производный класс с именем CompanyBot (который поставляется с примером игра), которые выполняют некоторую проверку столкновений в этом методе, так как он называется «думаю», мы можем предположить, что AI-код, как ожидается, также будет там. В то время как движок NeoAxis (в прошлый раз я изучал его) разделял ИИ и физику от сущностей.
Существует шаблон Controller, о котором я слышал. Возможно, вам следует поискать его, и это, вероятно, не совсем то, о чем я говорю, но звучит как хорошее решение.
источник