Определение попадает ли объект в поле зрения другого объекта довольно частое явление в сфере разработки игр.
Допустим у нас есть определённый угол и дистанция на которой может видеть другие объекты этот объект. Не имеет смысла бездумно пускать лучи во все стороны, что-бы определить, входит ли этот объект в область зрения. И не нужно их распределять по этому углу, через определённый шаг.
Для упрощения понимания что мы будем делать, на картинке будет представлена 2D версия поля зрения, для 3D ситуация идентична. Посмотрим же на картину.
Для того что-бы мы могли наградить способностью обнаружатся любой объект, мы введём интерфейс: “IDetectable”, который будет отвечать за логику объекта, который может быть увиден.
Область видимости
Так же ввёдем абстрактный класс “DetectionArea”, области видимости объекта, почему абстрактный? Всё для того, что-бы в будущем можно было ввести не только сферическую зону видимости, но и других форм. В абстрактном классе, хранятся все объекты, которые на данный момент находятся в области видимости.
В этом скрипте, содержится список всех находящихся в области видимости объектов, которые могут быть обнаружены нами.
Сферическая область видимости
Так же введём реализацию сферической области видимости, в которую передаётся дистанция видимости и локальная точка от которой идёт радиус сферы.
Обнаружение объектов
Основная логика же, находится в абстрактном классе Detection.
В классе Detection, мы перебираем каждый объект, находящийся в области видимости по дистанции, вычисляем дистанцию до него и направление.
После чего выпускаем луч из объекта до другого объекта для проверки, есть ли между ними препятствия. Если препятствия есть, мы говорим объекту, что его не обнаружили.
В ином случае, мы проверяем находится ли объект в зоне видимости по углу.
Если же он не находится в этой зоне видимости, мы также отсылаем ему сигнал, что он не обнаружен. В ином случае мы отсылаем ему статус того, что он обнаружен.
Весь этот метод работает в корутине, которую мы можем остановить/запустить вызвав методы: StartWatching, StopWatching. Дистанция и угол видимости мы можем менять в любой момент игры.
В моём случае, запуск этого скрипта, выполнен с помощью доп. Класса Enemy, который наследуется от класса Detection
Теперь, любой объект реализующий интерфейс IDetectable, будет исполнять свою логику при попадании в поле зрения объекта реализующего класс Detection, при этом мы можем так же поместить логику на объект, который может обнаружить другие объекты, но в этом руководстве, мы не стали этого делать, так как у нас стояла цель сделать именно поле зрения, которое будет зависеть от окружения, дистанции и угла обзора.
https://gist.github.com/AlexTox/a643cf8d4600a3a6c7bc9744d999c113