Вчера я прочитал презентацию от GDC Canada о системе сущностей Атрибут / Поведение, и я думаю, что это довольно здорово. Тем не менее, я не уверен, как использовать его практически, а не только в теории. Прежде всего, я быстро объясню вам, как работает эта система.
Каждый игровой объект (игровой объект) состоит из атрибутов (= данных, к которым можно обращаться как по поведению, но также по «внешнему коду»), так и по поведению (= логика, которая содержит OnUpdate()
и OnMessage()
). Так, например, в клоне Breakout, каждый кирпич будет состоять из (пример!): PositionAttribute , ColorAttribute , HealthAttribute , RenderableBehaviour , HitBehaviour . Последний может выглядеть так (это просто нерабочий пример, написанный на C #):
void OnMessage(Message m)
{
if (m is CollisionMessage) // CollisionMessage is inherited from Message
{
Entity otherEntity = m.CollidedWith; // Entity CollisionMessage.CollidedWith
if (otherEntity.Type = EntityType.Ball) // Collided with ball
{
int brickHealth = GetAttribute<int>(Attribute.Health); // owner's attribute
brickHealth -= otherEntity.GetAttribute<int>(Attribute.DamageImpact);
SetAttribute<int>(Attribute.Health, brickHealth); // owner's attribute
// If health is <= 0, "destroy" the brick
if (brickHealth <= 0)
SetAttribute<bool>(Attribute.Alive, false);
}
}
else if (m is AttributeChangedMessage) // Some attribute has been changed 'externally'
{
if (m.Attribute == Attribute.Health)
{
// If health is <= 0, "destroy" the brick
if (brickHealth <= 0)
SetAttribute<bool>(Attribute.Alive, false);
}
}
}
Если вы заинтересованы в этой системе, вы можете прочитать больше здесь (.ppt).
Мой вопрос относится к этой системе, но, как правило, к каждой компонентной системе. Я никогда не видел, как что-либо из этого действительно работает в реальных компьютерных играх, потому что я не могу найти хороших примеров, и если я найду один, он не будет документирован, там нет комментариев, и поэтому я не понимаю этого.
Итак, что я хочу спросить? Как разработать модели поведения (компоненты). Я читал здесь, на GameDev SE, что самая распространенная ошибка - создавать множество компонентов и просто «делать все компонентом». Я читал, что предлагается не выполнять рендеринг в компоненте, а делать это вне его (поэтому вместо RenderableBehaviour это может быть RenderableAttribute , и если для сущности RenderableAttribute установлен в значение true, то Renderer
(класс не связан с комплектующие, но для самого двигателя) должны ли нарисовать его на экране?).
Но как насчет поведения / компонентов? Давайте скажем , что у меня есть уровень, а на уровне, есть Entity button
, Entity doors
и Entity player
. Когда игрок сталкивается с кнопкой (это кнопка пола, которая переключается нажатием), он нажимается. Когда кнопка нажимается, она открывает двери. Ну а теперь как это сделать?
Я придумал что-то вроде этого: у игрока есть CollisionBehaviour , который проверяет, сталкивается ли игрок с чем-то. Если он сталкивается с кнопкой, он посылает CollisionMessage
к button
лицу. Сообщение будет содержать всю необходимую информацию: кто столкнулся с кнопкой. Кнопка имеет ToggleableBehaviour , который будет получать CollisionMessage
. Он проверит, с кем он столкнулся, и если вес этого объекта достаточно велик для переключения кнопки, кнопка переключается. Теперь он устанавливает для атрибута ToggledAttribute кнопки значение true. Хорошо, но что теперь?
Должна ли кнопка отправить другое сообщение всем другим объектам, чтобы сообщить им, что оно было переключено? Я думаю, что если бы я делал все так, у меня были бы тысячи сообщений, и это было бы довольно грязно. Так что, может быть, это и лучше: двери постоянно проверяют, нажата или нет кнопка, связанная с ними, и соответственно изменяют свой атрибут OpenedAttribute . Но тогда это означает, что метод дверей OnUpdate()
будет постоянно делать что-то (действительно ли это проблема?).
И вторая проблема: что, если у меня есть больше видов кнопок. Один нажимается давлением, второй переключается выстрелом, третий переключается, если на него льется вода и т. Д. Это означает, что мне придется вести себя по-разному, что-то вроде этого:
Behaviour -> ToggleableBehaviour -> ToggleOnPressureBehaviour
-> ToggleOnShotBehaviour
-> ToggleOnWaterBehaviour
Так работают настоящие игры или я просто тупой? Может быть, у меня может быть только один ToggleableBehaviour, и он будет вести себя в соответствии с атрибутом ButtonTypeAttribute . Так что, если это ButtonType.Pressure
, он делает это, если это ButtonType.Shot
, он делает что-то еще ...
Так что я хочу? Я хотел бы спросить вас, правильно ли я это делаю, или я просто глуп, и я не понял смысл компонентов. Я не нашел хорошего примера того, как компоненты действительно работают в играх, я нашел лишь несколько обучающих программ, описывающих, как создать систему компонентов, но не как ее использовать.
источник
Entity
есть свойEntityBody
, который абстрагирует все уродливые биты. Затем поведение может считывать позицию с позицииEntityBody
, прикладывать к ней силы, использовать суставы и двигатели, которые есть у тела, и т. Д. Наличие такой физики с высокой точностью воспроизведения, как Box2D, безусловно, приносит новые вызовы, но они довольно забавные, imo.Component
/System
схему, на которую ссылались несколько раз на досках. Наши реализации действительно имеют довольно много общего.