Если два объекта взаимодействуют, что содержит код взаимодействия?

28

Подумайте о пуле и враге или игроке и полу. Если эти объекты взаимодействуют, что содержит код взаимодействия?

ThatOneGuy
источник
2
Взаимодействовать каким образом? Вы имеете в виду обнаружение столкновений? Если это так, то, скорее всего, вы бы реализовали как класс обнаружения коллизий, так и менеджер разрешения коллизий.
CaptainRedmuff
Отчасти да, меня интересует как столкновение, так и то, что происходит после столкновения. Пуля проверяет, находится ли она близко к врагу или наоборот? И что происходит после столкновения, может ли объект пули просто сказать вражескому объекту, что он получил удар? Как вы можете видеть, я довольно смущен всем этим, и это делает очень трудным для чтения код.
ThatOneGuy

Ответы:

23

TL; DR:

Ваши игровые объекты не знают друг о друге и не проверяют другие объекты. Вы создаете шаблон обнаружения столкновений и разрешения столкновений, который проверяет ваши игровые объекты и выполняет соответствующие действия для имитации вашей игровой физики.

Хороший материал

Из предыдущих попыток написания обнаружения коллизий и чтения этой книги , есть два этапа для обнаружения коллизий и разрешения коллизий. Первый этап (обнаружение столкновений) - это ранний проход, на котором вы определяете, могут ли два объекта иметь потенциальное столкновение. Если какие-либо два объекта образуют потенциальное столкновение, вы затем передаете эти объекты на второй этап (разрешение столкновений), чтобы выполнить более точную проверку объектов и попытаться разрешить столкновение.

Где-то в вашем движке / игре вы будете хранить массив всех объектов в вашем мире. В каждом кадре вы должны проходить через массив и проверять каждый объект на предмет каждого другого объекта простым обнаружением столкновения ограничивающей рамки / сферы

псевдокод:

dectectCollisions(objects)
{
    for(objectA in objects)
    {
        for(objectB in objects)
        {
            if(objectA != objectB) //ignore self
            {
                if(BoundingSpheresIntersect(objectA, objectB))
                {
                    collisionResolver.addObjects(objectA, objectB);
                }
            }
        }
    }
}

Этот вид цикла довольно неэффективен, но оставляет место для улучшения за счет использования пространственного разделения в качестве раннего начала для объектов, которые гарантированно находятся слишком далеко друг от друга, чтобы столкнуться.

После проверки двух объектов на возможное столкновение (т.е. оба объекта находятся достаточно близко, чтобы столкнуться), объекты передаются для выполнения более точной процедуры обнаружения столкновения.

Представьте, что у вас есть два многоугольника случайных форм и размеров, которые достаточно близки, чтобы потенциально пересекаться, но не из-за их геометрии:

Изображение найдено через Google

Используя ограничивающие сферы, эти два объекта создали бы ложный положительный результат для потенциального столкновения. Здесь вы должны выполнить более тщательный проход, чтобы определить, действительно ли два объекта пересекаются.

Как только вы нашли истинное столкновение, ваш шаг разрешения столкновений затем выполнил бы соответствующее действие для разрешения объектов, применяя силы или моменты в зависимости от степени детализации и потребностей вашей игровой физики.

Имея это в виду, вы можете абстрагировать весь процесс обнаружения и разрешения коллизий, чтобы вашим объектам не нужно было ничего знать друг о друге, а также процесс, необходимый для определения и устранения коллизий. Два класса / менеджера, которые обрабатывают это для вас, должны знать только основные свойства каждого объекта, чтобы выполнить быструю и грязную проверку на наличие столкновений, а затем более тщательную проверку, если это потребуется.

CaptainRedmuff
источник
2
В частности, шаблон дизайна Mediator будет уместным. Шаблон Observer был бы хорошей альтернативой, у которой совсем другие цели. Вы можете получить довольно хорошее резюме о них в этом посте Stackoverflow .
kurtzbot
12

Один из способов, которым Unreal Engine 3 справляется с этим:

Пуля получает сообщение о столкновении, в котором говорится, что оно попало во что-то, с аргументом, сообщающим, что оно попало. Затем он может вызвать objectHit.takeDamage (self). Затем цель получает сообщение TakeDamage с указателем на предмет, который поразил ее, и предпринимает соответствующее действие.

Мне лично нравится такой подход, потому что он означает, что пуля может предпринимать особые действия (например, создавать какой-то эффект взрыва в зависимости от типа поражаемого предмета), а цель может предпринимать специальные действия в зависимости от типа пули.

Также возможно, что пуля знает, что она делает с целями, и может вызывать для нее функцию, например, objectHit.freeze (self). Тогда цель знает, что ее поразило что-то, что ее замораживает, и что это был за объект.

РЕДАКТИРОВАТЬ: Этот ответ предназначен для общего представления о том, как он может работать, так как вы, вероятно, не работаете с UE3. :)

Almo
источник
10

Вор сделал это очень хорошо в Темном Двигателе с Источниками и Рецептронами. У объекта могут быть оба этих свойства разных типов. Например, стрелка Water будет иметь источник для WaterStim при контакте. Взрыв будет иметь AoE FireStim.

Когда Стрелка Воды поражает объект, целевой объект затем ищет в своих Рецептронах все, что ищет WaterStim с соответствующими значениями интенсивности. Затем он выполняет любую команду, связанную с ним (в этом случае превращение горящего факела в выключенный факел и испускание клубов дыма).

Так как в SystemShock2 используется один и тот же движок, именно так обрабатываются все типы повреждений, разные пули имеют разные Стимсы, а разные монстры имеют Рецептроны для разных типов Стимов и наносят урон, равный 1 *, 2 *, 1 / 2 интенсивность в зависимости от того, является ли тип боеприпасов "супер эффективным" или нет.

Она казалась очень гибкой системой, поскольку вы могли добавлять источники и рецепторы к объектам в редакторе уровней (скажем, чтобы сделать одноразовую дверь, которая открывается при попадании в огонь). Хотя вы также можете сказать рецептору "отправить скрипт" сообщение ", если объект имеет специальные сценарии, связанные с ним.

То, что вы не хотите делать, это жестко закодировать матрицу взаимодействия nXn всех возможных объектов, сталкивающихся со всеми возможными объектами! Обобщая взаимодействия посредством стандартизированных сообщений, вы упрощаете процесс.

Ник
источник
С точки зрения сценариев этот подход кажется наиболее гибким и наиболее выразительным. Очень круто.
drhayes
-2

Одно из решений состоит в том, чтобы хранить контейнеры с пулями и игроками в отдельных классах, а затем иметь функцию main (), которая отвечает за взаимодействие цикла цикла.

ТР1
источник