Застрял в текстурах? Вам сюда! (По быстрому)
Привет, реакторчане! Хочу немного рассказать про 3d, разработку игр и контента, создаваемого для неё.
Сегодня расскажу, что такое текстуры и в чем мы все-таки застреваем в играх.
Для полной картины, думаю, стоит начать с самого начала - создания 3d модели и текстурирования.
За основу возьмем одну из простых фигур - куб. 3D модель, как многие уже знают, состоит из вершин (vertex) в трехмерном пространстве, соединенных гранями (edge) . Эти вершины и грани образуют полигон . Есть несколько типов полигонов: треугольный (tris), четырехугольный (quads) и ngone - полигон в котором более 4-х вершин. (рис1)
рис1.
Теперь, для текстурирования нашего объекта , нам необходимо создать UV развертку. Давайте сделаем это на примере картонной коробки, которую вы развернули на полу. Uv развертка - это ваша модель, развернутая в двумерном пространстве. Т.е все полигоны нашего объекта будут расположены в одних UV координатах (плоскости). (рис2).
рис2.
Наша модель готова к текстурированию! Разберемся что же такое текстура, в которой все застревают!? Текстура - это всего лишь 2d картинка (растровое изображение), используемое для придания фактуры и детализации нашей 3d модели, накладываемое по uv развертке и не более того. Обычно используют текстуру размером 1x1 т.е. 2048х2048. Пример: Рис3.
Рис3.
Теперь о главном! Так почему же объекты в играх застревают друг в друге, проваливаются сквозь пол, и отталкивают в космос?! Во всем виноваты коллайдеры (collider) и физика движка. Что же такое коллайдер? Если проще, то коллайдер - это такая же сетка из вершин и граней с помощью которой, физический движок просчитывает столкновения между объектами. Только эта модель не отображается. Есть несколько основных типов коллайдеров: Box collider,Sphere Collider, Mesh collider и другие (рис4) . Чем они проще (чем меньше полигонов ), тем быстрее движок просчитывает их взаимодействие. Из названий первых двух понятно, что эти коллайдеры представляют собой куб и сферу, а третий это сетка, которая в точности повторяет наш объект или её более упрощенный вариант.
Рассмотрим два первых вида на модели чайника, из известной программы 3dmax в не менее известном движке Unity.
Рис4.
При просчете физики используется модель коллайдера, а геометрия самого объекта не учитывается.
Пример.
При попытке прохождения одного коллайдера сквозь другой , они начинают отталкивать друг друга в противоположных направлениях.
Пример.
Так из-за чего тогда происходят застревания? - Из за ошибок в просчете физики. А если точнее, то из-за скорости её просчета. Если говорить простым языком, то проверка столкновений (и не только) объектов в игре производится несколько раз за определенное время. И если один объект попадает в другой, в промежутке между просчетами, получается знакомый нам эффект застревания.
Но если вдаваться в вопрос то это некорректно.
tl;dr, т.е. если лень читать, - объект не просто попал внутрь другого т.к. скорость слишком большая - он просто вылетит либо назад, либо вперед (за уровень). Застревание происходит потому что произошла какая-то дичь и движок охуел.
Во первых - в примерах показан и рассматривается конкретно юнити, в разных физических движках (а юнити использует весьма старый движок, и скоро перейдет на Havoc) реализация отличается.
Во вторых - рассмотрение в виде "объект попадает внутрь другого из-за скорости" - ошибочно.
Физика имеет разные варианты расчета. Используется, обычно, интерполяционный или эктраполяционный подход.
Первый значит следующее - объект в кадре 1 был в точке А, в кадре 2 по расчетам получился в точке Б. При просчете движения считается функция движения между А и Б, и если объект в какой-либо точке движения (читай - в точке формулы, с определенной точностью) прошел через препятствие - он будет вытоклнут назад, иначе (недостаточная точность) он просто не поймет что там было препятствие и окажется за ним.
Второй означает, что физика просчитана "наперед" - например, если объект "упругий", т.е. должен отлететь от препятствия. Тогда если он в следующем кадре (опять-таки в рамках точности формулы) во что-то влетит - можно просчитать насколько он отлетит или замедлится в рамках трения, например.
В любых современных движках, даже в юнити, такого сорта застревание, а именно то что называется "ааа пацаны в текстурах застрял", чаще обычно происходит не из-за косяков физики. Вертексная физика не имеет решений для такого сорта проблем (это выльется в уход в рекурсию) и в качестве крайнего средства выталкивает объекты друг из друга - т.е. никогда не вываливается в случай застревания в случае "коллайдер+коллайдер". Проблемы с этим видеть со всякими трупами в халфе или еще где-то где рэгдолл дохлого противника дергается как больной т.к. физика пытается вытолкнуть отдельные коллайдеры рэгдолла и сталкивается с противоречиями, например, с проблемами обратной кинематики (объекты из множества костей с сочленениями и неразрывными связями между ними) или с пачкой коллайдеров (куча камней с зачем-то сделанными отдельными коллайдерами стоят скопом и физика не понимает куда вытолкнуть объект - между ними ил наружу).
Такого сорта застревания происходят, чаще всего, наоборот из-за жестких ошибок в высокоуровневом коде - например персонаж помещается на полметра ниже пола т.к. какая-нибудь катсцена или еще что-то попросила это сделать, и эта команда отдалась физическому движку напрямую и кодер забыл ее удалить, или, да, из-за слишком больших скоростей - но не в результате "застревания в коллайдере", а в результате попадания между разными коллайдерами и противоречивыми командами типа "толкай сюда", "нет, выталкивай сюда". В итоге персонаж дрыгается или просто застревает.
Также указанный пример с толканием чайника - хорош как иллюстрация, но опять-таки использует фундаментально неверный костыль. Толкая в плеймоде (игра запущена в редакторе юнити) чайник изменяются его математические координаты, т.е. в юнити - transform. Это _не является физическим просчетом_ и физика считает это как "телепортацию" - т.е. в каждом кадре внезапно обнаруживает что чайник без видимой причины изменил местоположение, хотя к нему не было приложено силы, и перерасчитывает _всю_ физику. Если его протолкнуть в превью через коллайдер, читай - тянуть достаточно сильно - он пролетит насквозь, при этом он не сделал бы это под воздействием реальной силы, указанной через физический движок, т.к. сработала бы экстраполяция/интерполяция, в зависимости от его настроек. Это также дико негативно влияет на производительность.
Также: сферическая модель коллайдера, как и цилиндрическая, не является мешем или вообще структурой, состоящей из полигонов. Физика расчитывает ее в виде формул, исходящих из радиуса, т.к. это проще и точнее для физических расчетов коллизий между двумя телами, поэтому объяснение этих моделей столкновений через вершины (вертексы) и полигоны также не верно (как и для box коллайдера, который описывается как центр+ширина/высота и использует их формулы вместо вертексов). Хорошим примером является физика колес, которая также есть в юнити, и именно поэтому коллайдеры, отличные от коробки-сферы-цилиндра являются глючными, тормозными и не рекомендуются к использованию т.к. физике сложно их математически обсчитать.
Одним из банальных примеров того что даже в архаичной физике не происходит застреваний на основе скорости является первый дум и спидраннерский трюк Void Glide - если объект движется настолько быстро что в первом кадре просчета находится строго "до", а во втором - строго "после" препятствия, то он вылетает наружу (и можно выйти за пределы уровня), т.к. там использовалась исключительно экстраполяция между начальной и конечной точкой без учета интерполяции и физика считалась по игровым тактам.
Извините за простыню.