— Бляха-муха, Нейт! Ты хоть предупреждай! — Возмущенно цикнул он, сбрасывая оцепенение.
— Ага, щас. Чтобы ты успел подготовиться к атаке? — Я с усмешкой бросил лук на мягкий диван.
— Нейт прав. — Дэвид тут же сграбастал музейный экспонат, с любопытством поглаживая полированную рукоять. — Расстояние теперь было в два раза меньше. Плюс фактор неожиданности. То есть, по самым грубым подсчетам… ты среагировал примерно за сто миллисекунд. Для того чтобы уворачиваться от пуль в упор, этого, конечно, недостаточно. Но…
— От удара или чего-нибудь летящего, типа сраной подствольной гранаты, уйти вполне реально. — Мрачно завершил за него Коул, глядя на свои руки. — И это я еще в обычной, человеческой форме…
Парень в задумчивости прошелся по гостиной до большого стола, где красовалась огромная пластиковая диорама подводного города. На центральной площади из блоков застыла эпичная сцена — из-под земли на площадь выбирались акулолюди. Вторжение шло полным ходом. То не стояло на паузе. Кора не успела доиграть перед школой, из-за чего композицию пришлось оставить как есть, под расписку, то мы ничего не будем трогать.
Сграбастав стоящую на краю стола наполовину пустую бутылку воды, Коул жадно отхлебнул и задумчиво уставился на нас с Дэвидом.
— Слушай, кстати о стрелах… У меня затык возник как раз с регистрацией попаданий.
— Какой именно? — Я мгновенно снял метафорическую зеленую шапочку лучника и надел высокий цилиндр лид разработчика. Жаль монокля не было.
— Проблема в системе коллизий. Которая обрабатывает соприкосновения объектов через метод ОнТриггер. Она тупо ломается на быстрых объектах. — Пояснил парень. Он подобрал стрелу и медленно провел ею по воздуху, наглядно имитируя полет. — Когда стрела летит, движок чекает ее координаты каждый тик, то есть каждые пятьдесят миллисекунд. И если в момент проверки коллайдер стрелы пересекается с коллайдером моба, игра фиксирует попадание. Но…
Парень сделал тяжелую паузу, явно успев сломать об эту проблему мозг.
— Может, я, конечно, дебил… Но вот что происходит, если стрела прошивает хитбокс объекта между двумя этими проверками. Ну, вот, например, стрела влетает в твою модельку ровно на пятьдесят первой миллисекунде. За оставшиеся сорок девять миллисекунд до следующего тика движка она успевает пролететь сквозь тебя насквозь! Игра просто не успевает зарегистрировать пересечение полигонов. И, короче, вот это гребаное квантовое туннелирование я вообще не понимаю, как нормально пофиксить.
Я задумчиво пожевал губу. Проблема классическая, но для новичка в геймдеве неочевидная. Дискретное обнаружение столкновений — игра опрашивает координаты по таймеру, а в промежутках между тиками объект фактически телепортируется из точки А в точку Б. Для оптимизации это мастхэв, система жрет мало ресурсов и идеально работает с медленными тушками мобов или статичными блоками. Но стоит добавить быстрые снаряды — и всё, движок не успевает раздуплиться. Стрелы начинают нечестно мазать, а если разогнаться на вагонетке то можно проскочить сквозь стену. В моей прошлой практике я лично с этой проблемой не ковырялся — на то у меня были работяги.
Так что пришлось пару минут молча понаматывать круги по ворсистому ковру, роясь в чертогах разума. И решение всплыло. Память услужливо подкинула обрывки пьяной беседы с лид-программистом из прошлой жизни на каком-то корпоративе, одном из сотни похожих. Мы тогда отмечали релиз бодрого аренного шутера, клона «Овервотча» — правда, с мыльной графикой и названием, больше смахивающим на средство от запора.
Подняв свою стрелу, я подошел к Коулу и медленно провел ею по воздуху, уткнув затупленный наконечник ему прямо в грудь.
— Короче, тебе нужно проверять не точечное положение коллайдера в пространстве каждый тик. Это залупа не будет работать. Тебе нужно чекать саму траекторию полета. — Я плавно протащил стрелу под рукой у парня, демонстрируя вектор движения. — Таким образом, движку будет плевать, где физически находится снаряд между кадрами. Он будет проецировать вектор от прошлой точки к текущей и математически просчитывать, пересек ли этот отрезок чужой хитбокс.
Коул на секунду замер и мельком зыркнул в сторону прихожей, словно уловил шаги на улице. Затем забрал у меня стрелу, понимающе цокнув языком.
— А что, если просто пускать некий Рейкаст (целеуказатель)? Типа невидимого лазерного луча из наконечника стрелы в сторону полета. Нацепить скрипт прямо на префаб стрелы, и пусть каждый кадр бросает луч на расстояние, равное дистанции, которую стрела пролетит до следующего тика. Если луч во что-то утыкается, то регаем попадание…
Закончить мысль парень не успел, да и не было в этом нужды. Суть он уловил, а значит противный баг с миссами считай пофикшен. В этот момент в прихожей тяжело хлопнула массивная входная дверь, и тишину дома тут же разорвал звонкий детский голосок. Судя по обрывкам фраз, Кора вовсю пересказывала Авроре события какого-то мультика.