Игровое зрение

Это перевод статьи уважаемого PD-механика, программиста и просто хорошего багета парня LordShinjo. Для тех, кто читал его оригинал, все равно будет кое-что новое — в основном я сгорю буду говорить о том, почему всё плохо, какие проблемы с видимостью имеются в доте и как они были решены.


Любому, кто запускал  WC3, известно, что на экране можно увидеть какие-то модельки, декорации, ландшафт и прочая. Это логично — играть вслепую было бы сильно неудобно, хотя и весьма забавно с точки зрения зрителей.


Как правило, юниты-объекты имеют своё поле зрения и не могут видеть, что находится за одним-единственным деревом перед ними. Впрочем, есть летающие юниты, которые легко видят через препятствия — но, опять же, бывают преграды, через которые не способны подсматривать даже они.

Как вообще игра обрабатывает зрение?

Архитектура сети

Если здесь как-то оказались люди, родившиеся в конце 90-х или начале 00-х, то они, скорее всего, не знают о тайлах. Blizzard не особо горели желанием изобретать велосипеды, да и вообще 2000-е были годом прорывов в игрострое, поэтому разработку  WC3 продолжили на основе старых движков с тайлами. Так что сетка — часть жизни всего варкрафта, и без неё всё тлен.

Каждая ячейка на картинке имеет сторону 128x128, в особых единицах измерения варкрафта. Обычно эту дистанцию имеют «юнит», и отличить её от привычного юнита как объекта (монстра) можно только по контексту. Ну что поделать, если английский язык так универсален и является основой любого мапмейкинга?

Warcraft 3 map grid

Одно из преимуществ тайлов — возможность создания простого и быстрого поиска пути. По сути, каждый раз, когда юниту нужно двигаться, путь прокладывается по конкретным «контрольным» тайлам, чекпоинтам, если угодно. В «пластилиновом» движке над ИИ и просчетом путей приходится работать намного больше, откуда и появляются чудесные картины "тупого ИИ, бегущего в стену".

В  DotA2 от тайлов отказались. В результате — 5 лет не могут починить проблемы с неверно проложенными путями.
Я на личном опыте убедился в гениальности алгоритмов, когда мой герой не смог взять руну, лежащую прямо перед ним. Вместо этого он трижды (я трижды останавливал его и нажимал заново) пытался убежать в сторону мида. Пока шел таймер респауна, я подбирал самые обидные рифмы на «габен», но ничего свежего не придумал.

В  Dota2Reborn тайлы вновь вернулись — больше никакого пластилина. Впрочем, размер каждого тайла сделали примерно 32x32, поэтому гибкость достаточно велика. Но при этом карта стала больше напоминать старый добрый варкрафт, а это не может не радовать.

Сейчас видимость в  д2 может даваться в конкретной зоне, а не просто в каких-то квадратах. В реборне — нужно внимательно тестить, а лень.

6.83

Vision and Fog of War can now be any numerical value, rather than specific intervals (previously it was 0, 64, 192, 320, 448, 576, 704, 800, 832, 960, 1088, 1216, 1344, 1472, 1600, 1728)
Previously if you had a vision between the fixed intervals, it would clamp to a fixed value.

0.4 секунды хватит всем

Чтобы не перенагружать топовые третьи Пентиумы,  близзы решили оптимизировать развертку карты при помощи увеличения периодичности подсчетов. Т.е. разработчики постановили, что игра должна идти и проверять все-все-все ячейки на туман войны и видимость строго каждые 0.4 секунды и не чаще.

Каждые 0.4 секунды подсчитывается, какие клетки видны юниту, и с них снимается туман войны, и возвращается на те, где уже ничего не видно.

На минутку, эти подсчеты уникальны для каждого живого игрока. То, что вы видите союзников, является одной из опций альянса, и при желании её можно отключить триггерами. Я однажды планировал использовать эту фичу для какого-нибудь мода, но до практики дело так и не дошло. Итак, на каждую ячейку карты каждые 0.4 секунды проходит 10 проверок на видимость, по одной на каждого игрока.

Чтобы не показывать игроку угловатые ячейки, близзы реализовали систему умного затемнения и осветления. Как только новая клетка открывается или закрывается, на неё вроде бы «медленно» наползает туман, но на самом деле видимость уже полностью утрачена (или получена). Например, на клетке, закрывающейся за спиной, может появиться враг, но его уже не будет видно, даже если технически центр модели всё еще попадает в видимую зону. Аналогично при ночных погонях за кем-то модель врага "мерцает" из-за того, что он переходит с клетки на клетку быстрее, чем обновляется туман. Движок видит, что юнит наступает на клетку, невидимую врагу, и прекращает рисовать модельку.

В  DotA2 от подобной оптимизации, естественно, отказались. Даром, что эта дура из 2010 года без физики и с одной натянутой текстурой умудряется подвешивать неплохие системы. Но в чем их не упрекнешь, так это в удобстве. Если ты гонишь кого-то ночью, и скорости примерно равны, никакого мерцания не будет. Аналогично нет проблем со стрелой  WR — подсвечивается весь путь полета. В  Dota1 из-за высокой скорости движения (стрела закончится где-то за 0.5 секунд) подсветится максимум 1 участок где-то по пути.

Нужно построить зигг… велосипед

Официально редактор  варкрафта позволяет указать каждому юниту ночной и дневной обзор. Внешне кажется, что можно указать любое число, но всё намного хитрее. Для справки — большинство юнитов по умолчанию имеют обзор 1800/800 (д/н).

Минимальный обзор — 0 (логично), а максимальный — 1800 (не совсем логично). Продолжим, что мы оперируем с тайлами, а не реальным расстоянием. Отсюда можно быстро сделать выводы: близзы дали нам в лучшем случе 15 уровней обзора, по +128 за каждый.

Таблица с уровнями обзоров.

Всё, что выше, просто не работает, и обрезается до 14-го уровня. Можно предположить, что близзарды решили обойтись одним байтом, а последний слот ушел под «обзор = -1» или что-нибудь подобное.

По этой причине реализовать толком  Moon Shard в первой дотке проблематично. Абилка, меняющая дальность обзора, не может обойти этот лимит. Так что  баланар или  сларк по ночам видит с Moon Shard ничуть не больше обычного. Келлер уже предлагал выдавать таким уникумам по несколько дополнительных дамми, которые бы окружали героя на некотором расстоянии и симулировали увеличение обзора, но подобную систему все равно непросто вписать в тесные условия дотки.

На уровне 0 юнит не видит себя и его нельзя выделить, не имея чужого обзора над ним. В  DotA2 нулевой обзор позволяет увидеть модельку юнита и ничего кроме. Это используется для  Bloodseeker и его пассивки, подсвечивающей врагов. А почему же в олдскульной дотке всё иначе?

  1. Движок не понимает подобных махинаций. Из-за клеточной основы он требует обзора над конкретной клеткой, а их обновляют лишь раз в 0.4 секунды. Отсюда — мерцание.
  2. Просто взгляните на то, сколько открывает обзор ниже 320. Фрог использует даммиков с обзором 100, убивая их на месте. Радиус обзора — никакущий. Поэтому цель постоянно мелькает и уходит из видимости.
  3. Единственная возможность отрисовывать модельки в тумане войны хорошо известна мапхакерам. По сути, движок умеет и легко способен на подобные фокусы. Проблема в том, что близзы так и не желают делать новый патч для старой игры, продолжая надрачивать на доходы с WoW.

Наконец, одно из не портированных изменений 6.84 — снижение обзора курьера с 400 до 300. Если глянуть на картинки, будет понятно, почему. Даже на 400 обзора на включенном Burst он может успеть вылететь на долю секунду из кадра. На 300 он пропадает из кадра даже при обычном движении.

Смена дальности обзора

«Умные», плавные алгоритмы затемнения используются не только для подсветки новых клеток. Когда обзор юнита изменяется, будь то смена дня и ночи, либо получение способности, дающей бонусный обзор, новые клетки открываются или закрываются постепенно. В среднем на каждую клетку уходит по 0.4 секунды. Например, когда ночь сменяется днём, можно увидеть, как каждые 0.4 секунды открывается новая клетка.

Смена обзора происходит одновременно во всех направлениях.

А теперь немного о практическом использовании.


Возьмем для примера  Winter Wyvern. Она умеет превращаться в летающую форму, причем обзора у этой формы нет — его обеспечивает наземный дамми-юнит. Т.е. задумывалось, что способность просто дает полет, но не меняет тип обзора на летающий. Но невооруженным глазом видно, что  виверна получает обзор летающего юнита при активации скилла, пусть он и пропадает через несколько секунд.

Проблема в том, что тип обзора определяется юнитом, а вот сам обзор мгновенно не закрывается — работает «плавный» алгоритм сокрытия. Когда  виверна переходит в летающую форму, движок, на очередном обновлении сетки, видит летающего юнита, и выдает ему соответствующий обзор без учета препятствий. В то же время уже работает цикл, закрывающий клетки одну за другой.

С аналогичной проблемой я столкнулся при создании нормального даггера для  спектры и сеток для  бруды. Герои просто превращаются в летающие аналоги, но обзор при этом некоторое время остается летающим, что явно излишне. В конечном итоге пришлось свести всё к тому, что  бруда и  спектра не имеют своего обзора вообще — за ними постоянно следует специальный наземный дамми. Аналогичные манипуляции проводятся с иллюзиями.

Другой популярный летающий морфер —  Batrider — от рождения имеет сильно порезанную дальность обзора, предполагаю, именно из-за этой фичи. Просто на момент его появления фрог еще не додумался до использования даммиков.


Теперь история №2. С 84 версии Nightmare от  Bane забирает у цели весь обзор. В  DotA2 игрок может увидеть только собственный силуэт. У нас же такой роскоши нет — герой исчезает полностью. Кто играл в первые бетки 84-й версии, может помнить, что реализация была не лучшей. Т.е. после усыпления еще около 3 секунд туман только сворачивался, а по окончанию длительности сна — еще столько же разворачивался. Это и был тот самый «умный» алгоритм плавной разветки, который просто ломал скил. По сути, еще 3 секунды после пробуждения игрок не мог делать ничего, т.к. не видел своего героя. Что делать?

Решение было найдено достаточно быстро — алгоритм не проверяет лимиты предоставленных ему данных. Т.е. выдав юниту абилку на -9999 обзора туман закрывался практически мгновенно — из-за огромной разницы алгоритму потребовалось ускорить процесс, закрывая сразу пачки клеток, а не по одной, как обычно. Аналогично, при помощи абилки на 99999 дальности обзора, выданной на долю секунды, восстанавливается нормальный обзор.

Последний взгляд

Умирающий юнит имеет уникальную область видимости, настраиваемую внутри игровых констант. Для доты — стандарт 500. Т.е. каждый умирающий юнит, чей обзор превышает 500, будет «сокращен» до этого значения. Длится эффект, опять же, некоторое время, указанное в константах — 5 секунд для доты. На этой «фиче» основан баг, что выкуп после смерти оставит героя с этими 500 обзорами до следующей смерти. Естественно, аналогичная ситуация произойдет, если герой просто умер и ооочень быстро возродился, например, из-за  блудстона.

Как отметил автор, этот баг возникает только после того, как юнит пройдет хотя бы раз через смену обзора день-ночь. По этой причине баг был незаметным в прошлых версиях, когда возрождение на 1м уровне занимало 4 секунды — все успевали получить второй к началу ночи. Сейчас же респаун занимает 8 секунд на первом уровне.

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


Фоторепортаж с места событий бага предоставил Agentura.

В моей дотке даммики крепятся при каждом возрождении в целом, независимо от метода, поэтому слепых героев больше нет.

Препятствия

Декорации — деревья, камни и пр. — могут блокировать обзор юнитов. Такие декорации зовут препятствиями.
К.О.

Движок считает, что в клетке стоит препятствие, только если оно занимает её нижний правый угод.

Препятствие может блокировать обзор всего по 4 шаблонам.

Если юнит окружен несколькими препятствиями, маска считается суммой всех масок.

Чтобы полностью заблокировать обзор юнита, необходимо 8 препятствий, окружающих юнита в каждой клетке.

Высота

Прекрасно известно, что, будучи выше дерева, можно увидеть, что происходит за ним, словно препятствия нет. Здесь всё дело в высоте самого препятствия.

По умолчанию деревья имеют высоту 230, за исключением особо больших Canopy Tree — их рост 300.

Как и в случае дальности обзора,  близзы используют в высотах не конкретные значения, а уровни. В данном случае — уровни скал (cliff level). Каждый уровень соответствует разнице высот в 128.



На картинке раста стоит на скале (уровень 1) и видит перед собой деревья высотой 230 (уровень 2), поэтому не может видеть, что происходит за ними.

В примере от Shinjo


Дерево на севере имеет высоту 3 уровня, дерево на западе — второго, а юнит стоит в центре на скале второго уровня.

Юнит может менять уровень, на котором находится, только меняя уровень скалы. Если на том же уровне нарисованы неровности, например, горка:



То уровень скалы по-прежнему остается «родным» и не меняется, поэтому за деревом ничего не видно. Нужно менять именно уровень.

При подъеме на следующий уровень обзор обновляется только при активации верхнего сегмента клетки-лестницы.


Пока юнит стоит на красной зоне, он не видит ничего, что выше.

Летающие юниты

По умолчанию летающие юниты считаются как юниты, стоящие на максимальном уровне скалы, поэтому к ним не применяются никакие препятствия.


Если у меня есть крылья, почему я хожу пешком?

Модификаторы тумана

В игре также есть объекты «модификаторы тумана». Они используются и самими blizzard, например, в абилках  Mirror Image или Storm, Earth and Fire (более известной как  Primal Split). В случае Mirror Image радиус устанавливается в настройках абилки, а длится модификатор ровно столько, сколько времени занимает разделение на копии. В Primal Split механика иная — модификатор всегда дает такой же обзор, что имел кастер, и длится 3 секунды.

Как и обычные радиусы обзора, модификаторы работают уровнями, и, грубо говоря, летают — их не блокируют никакие препятствия.

Есть еще один источник модификаторов — юниты. Каждый раз, когда юнит атакует цель из тумана или применяет заклинание на цель, создается модификатор тумана вокруг агрессора, и этот модификатор принадлежит цели агрессии. Радиус и длительность этого модификатора настраиваются в константах карты, для доты по умолчанию — 200. Длительность в файле не указана, и меня не отпускает чувство, что где-то в коде модификаторы создаются вручную, без участия  WC3, и поэтому длительность хардкодного модификатора равна нулю. Но я могу ошибаться — не исследовал эту часть.

Пещера Roshan

Нельзя увидеть, что происходит внутри логова рошана, если в комплекте нет чего-нибудь, что дает летающий обзор. Этот эффект достигается при помощи особых препятствий — блокираторов обзора.

По сути, это те же деревья, однако они не имеют физического тела и сквозь них можно свободно ходить. Плюс есть блокираторы воздушного обзора — единственное, что вообще может помешать летающих юнитам.

Блокираторы работают в обе стороны.



Красиво уложенная новая пещера рошана

И, для истории, старая пещера:



Маленький абуз курьера

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

Фрог, по привычке, скопировал для кнопок "принести предметы", "подобрать мои предметы" и "продолжить доставку" одного и того же дамми-юнита. Особенность этого дамми в том, что у него есть обзор — 800/800 или что-то подобное. Каждый раз, когда активируются эти «способности», создается и мгновенно скрывается такой даммик. Но при этом обзор, который он дает, остается.

В последних версиях моей карты это исправлено, а в LoD исправлено очень давно. У фрога же можно смело использовать курьер как разведку, спамя хоткеи и рассеивая туман в радиусе вдвое большем, чем обычно.

27 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.