Что такое меш в unity
Меши (Meshes)
Meshes составляют большую часть создаваемых вами трёхмерных миров. Unity не имеет встроенных инструментов для моделирования геометрии, разве что за исключением некоторых плагинов Asset store. Но несмотря на это, Unity поддерживает работу со многими пакетами трёхмерной графики. Unity также поддерживает работу с мешами, которые состоят как из трёхсторонних, так и из четырёхсторонних полигонов. Неоднородные рациональные безье-сплайны (Nurbs), неоднородные рационально сглаживаемые сетки (Nurms) а также высокополигональные поверхности должны быть конвертированы в полигоны.
3D форматы
Импортирование мешей в Unity может быть выполнено с помощью двух основных типов файлов:
Любой из этих типов позволит вам добавлять свои меши в Unity, но есть соображения относительно того типа, который вы выберите:
Экспортированные 3D файлы
Преимущества:
Недостатки:
Собственные файлы 3D приложений
Преимущества:
Недостатки:
Здесь находится перечень поддерживаемых пакетов трёхмерной графики, другие же чаще всего экспортируют вышеупомянутый тип файла.
Текстуры
При импорте меша, Unity попытается используя свой метод поиска, автоматически найти текстуры, используемые им. Сперва импортёр начнёт искать подпапку Textures, внутри папки с мешем или в папках уровнем выше. Если это не поможет, тогда по всей структуре проекта будет выполнен глобальный поиск всех имеющихся текстур. Конечно данный метод поиска значительно медленнее обычного и его главным недостатком является то, что в результатах поиска может появиться две и более текстур с одинаковым названием. В таком случае нет гарантий того, что нужная текстура будет найдена.
Textures в или над уровнем с компонентами (ассетами)»> Разместите свои текстуры в папке Textures в или над уровнем с компонентами (ассетами)
Создание и присвоение материала
Для каждого импортированного материала, Unity применит следующие правила:-
Если генерация материала отменена (иначе говоря если галочка Import Materials не выставлена), тогда будет назначен материал по-умолчанию. Если же генерация была включена, тогда произойдёт следующее:
Коллайдеры (Colliders)
Анимации (Animations)
Анимации автоматически импортируются из сцены. Для более детального ознакомления с настройками импорта анимации посетите главу документации под названием подготовка компонентов и их импорт в системе анимации (Mecanim).
Карты нормалей и персонажи (Normal mapping and characters)
Если вы конвертируете чёрно-белое изображение в карту нормалей, вам не следует об этом беспокоиться.
Формы смешивания (Blendshapes)
Есть два способа импорта форм смешивания с нормалями:
Советы (Hints)
Редактор Unity отображает гораздо больше вершин и треугольников (по сравнению с тем, что отображается в моём трёхмерном приложении).
Так и есть. На что вы действительно должны обратить внимание, так это на то, какое количество вершин/треугольников на самом деле было послано для просчёта на графический процессор (GPU). В отличие от случаев, где материал требует, чтобы эти данные посылались на GPU дважды, такие вещи как твёрдые-нормали (hard-normals) и несмежные UV развёртки(non-contiguous UVs) намеренно отображают гораздо большее количество вершин/треугольников, чем есть на самом деле. В контексте UV и 3D пространства треугольники должны располагаться смежно, чтобы сформировать собой границу, поэтому при уменьшении количества треугольников на UV-швах, которые и должны были образовать собой границу и возникает эффект мнимого увеличения их количества.
Meshes
Meshes составляют большую часть создаваемых вами трёхмерных миров. Unity не имеет встроенных инструментов для моделирования геометрии, разве что за исключением некоторых плагинов Asset store. Но несмотря на это, Unity поддерживает работу со многими пакетами трёхмерной графики. Unity также поддерживает работу с мешами, которые состоят как из трёхсторонних, так и из четырёхсторонних полигонов. Неоднородные рациональные безье-сплайны (Nurbs), неоднородные рационально сглаживаемые сетки (Nurms) а также высокополигональные поверхности должны быть конвертированы в полигоны.
Textures
При импорте меша, Unity попытается используя свой метод поиска, автоматически найти текстуры, используемые им. Сперва импортёр начнёт искать подпапку Textures, внутри папки с мешем или в папках уровнем выше. Если это не поможет, тогда по всей структуре проекта будет выполнен глобальный поиск всех имеющихся текстур. Конечно данный метод поиска значительно медленнее обычного и его главным недостатком является то, что в результатах поиска может появиться две и более текстур с одинаковым названием. В таком случае нет гарантий того, что нужная текстура будет найдена.
Place your textures in a Textures folder at or above the asset’s level
Material Generation and Assignment
Для каждого импортированного материала, Unity применит следующие правила:-
Если генерация материала отменена (иначе говоря если галочка Import Materials не выставлена), тогда будет назначен материал по-умолчанию. Если же генерация была включена, тогда произойдёт следующее:
Colliders
При перемещении своего объекта по сцене (к примеру машины), вы не можете использовать меш коллайдеры. Вместо этого, вам необходимо использовать примитивные коллайдеры. В этом случае вам необходимо отключить опцию Generate Colliders.
Animations
You can import animations from a Model file. Follow the guidelines for exporting FBX files from your 3D modeling software before importing it into Unity.
Normal mapping and characters
Если у вас есть модель персонажа с наложенной на него картой нормалей, взятой с высокополигональной модели, тогда вам необходимо будет импортировать в сцену версию модели для игры с Smoothing angle в 180 градусов. Таким образом можно предотвратить появление странно выглядящих швов в местах сочленения модели. Если же швы всё ещё останутся даже после применения данных настроек, тогда активируйте опцию Split tangents across UV seams.
Если вы конвертируете чёрно-белое изображение в карту нормалей, вам не следует об этом беспокоиться.
Blendshapes
Есть два способа импорта форм смешивания с нормалями:
Если вам нужны касательные на ваших формах смешивания, тогда выставите режим импорта Tangents в положение Calculate.
Hints
The Unity Editor shows too many vertices or triangles (compared to what my 3D app says)
Так и есть. На что вы действительно должны обратить внимание, так это на то, какое количество вершин/треугольников на самом деле было послано для просчёта на графический процессор (GPU). В отличие от случаев, где материал требует, чтобы эти данные посылались на GPU дважды, такие вещи как твёрдые-нормали (hard-normals) и несмежные UV развёртки(non-contiguous UVs) намеренно отображают гораздо большее количество вершин/треугольников, чем есть на самом деле. В контексте UV и 3D пространства треугольники должны располагаться смежно, чтобы сформировать собой границу, поэтому при уменьшении количества треугольников на UV-швах, которые и должны были образовать собой границу и возникает эффект мнимого увеличения их количества.
Особенности работы с Mesh в Unity
Компьютерная графика, как известно, является основой игровой индустрии. В процессе создания графического контента мы неизбежно сталкиваемся с трудностями, связанными с разницей его представления в среде создания и в приложении. К этим трудностям прибавляются риски простой человеческой невнимательности. Учитывая масштабы разработки игр, такие проблемы возникают либо часто, либо в больших количествах.
Борьба с подобными трудностями навела нас на мысли об автоматизации и написании статей на эту тему. Большая часть материала коснется работы с Unity 3D, поскольку это основное средство разработки в Plarium Krasnodar. Здесь и далее в качестве графического контента будут рассматриваться 3D-модели и текстуры.
В этой статье мы поговорим об особенностях доступа к данным представления 3D-объектов в Unity. Материал будет полезен в первую очередь новичкам, а также тем разработчикам, которые нечасто взаимодействуют с внутренним представлением таких моделей.
О 3D-моделях в Unity — для самых маленьких
При стандартном подходе в Unity для рендеринга модели используются компоненты MeshFilter и MeshRenderer. MeshFilter ссылается на Mesh — ассет, который представляет модель. Для большинства шейдеров информация о геометрии является обязательной минимальной составляющей для отрисовки модели на экране. Данные же о текстурной развертке и костях анимации могут отсутствовать, если они не задействованы. Каким образом этот класс реализован внутри и как все там хранится, является тайной за энную сумму денег семью печатями.
Снаружи меш как объект предоставляет доступ к следующим наборам данных:
Ядро движка (UnityEngine (native)) изолировано от скриптов разработчика, и обращение к его функционалу реализовано через библиотеку UnityEngine (C#). Фактически она является адаптером, поскольку большинство методов служат прослойкой для получения данных от ядра. При этом ядро и вся остальная часть, в том числе ваши скрипты, крутятся под разными процессами и скриптовая часть знает только список команд. Таким образом, прямой доступ к используемой ядром памяти из скрипта отсутствует.
О доступе к внутренним данным, или Насколько все может быть плохо
Для демонстрации того, насколько все может быть плохо, проанализируем объем очищаемой памяти Garbage Collector’ом на примере из документации. Для простоты профилирования завернем аналогичный код в Update метод.
Мы прогнали данный скрипт со стандартным примитивом — сферой (515 вершин). При помощи инструмента Profiler, во вкладке Memory можно посмотреть, сколько памяти было помечено для очистки сборщиком мусора в каждом из кадров. На нашей рабочей машине это значение составило
Это довольно много даже для нагруженного приложения, а мы здесь запустили сцену с одним объектом, на который навешен простейший скрипт.
Важно упомянуть об особенности компилятора .Net и об оптимизации кода. Пройдясь по цепочке вызовов, можно обнаружить, что обращение к Mesh.vertices влечет за собой вызов extern метода движка. Это не позволяет компилятору оптимизировать код внутри нашего Update() метода, несмотря на то, что DoSomething() пустой и переменные x, y, z по этой причине являются неиспользуемыми.
Теперь закешируем массив позиций на старте.
В среднем 6 Кб. Другое дело!
Такая особенность стала одной из причин, по которой нам пришлось реализовать собственную структуру для хранения и обработки данных меша.
Как это делаем мы
За время работы над крупными проектами возникла идея сделать инструмент для анализа и редактирования импортируемого графического контента. О самих методах анализа и трансформации поговорим в следующих статьях. Сейчас же рассмотрим структуру данных, которую мы решили написать для удобства реализации алгоритмов с учетом особенностей доступа к информации о меше.
Изначально эта структура выглядела так:
Здесь класс CustomMesh представляет, собственно, меш. Отдельно в виде Utility мы реализовали конвертацию из UntiyEngine.Mesh и обратно. Меш определяется своим массивом треугольников. Каждый треугольник содержит ровно три ребра, которые в свою очередь определены двумя вершинами. Мы решили добавить в вершины только ту информацию, которая нам необходима для анализа, а именно: позицию, нормаль, два канала текстурной развертки (uv0 для основной текстуры, uv2 для освещения) и цвет.
Спустя некоторое время возникла необходимость обращения вверх по иерархии. Например, чтобы узнать у треугольника, какому мешу он принадлежит. Помимо этого, обращение вниз из CustomMesh в Vertex выглядело вычурно, а необоснованный и значительный объем дублированных значений действовал на нервы. По этим причинам структуру пришлось переработать.
В CustomMeshPool реализованы методы для удобного управления и доступа ко всем обрабатываемым CustomMesh. За счет поля MeshId в каждой из сущностей имеется доступ к информации всего меша. Такая структура данных удовлетворяет требованиям к первоначальным задачам. Ее несложно расширить, добавив соответствующий набор данных в CustomMesh и необходимые методы — в Vertex.
Стоит отметить, что такой подход не оптимален по производительности. В то же время большинство реализованных нами алгоритмов ориентированы на анализ контента в редакторе Unity, из-за чего не приходится часто задумываться об объемах используемой памяти. По этой причине мы кешируем буквально все что можно. Реализованный алгоритм мы сначала тестируем, а затем рефакторим его методы и в некоторых случаях упрощаем структуры данных для оптимизации времени выполнения.
На этом пока все. В следующей статье мы расскажем о том, как редактировать уже внесенные в проект 3D-модели, и воспользуемся рассмотренной структурой данных.
Meshes
Meshes make up a large part of your 3D worlds. Unity provides a modeling tool called ProBuilder and there are also some Asset store modeling plugins, such as Mesh Deformer, UModeler, and Mesh Editor. And Unity has great interactivity with most 3D modeling software.
Unity supports triangulated or quadrangulated polygon Meshes, so you must convert Nurbs, Nurms, and Subdiv surfaces to polygons.
Textures
Unity follows a specific search plan to automatically look for the Textures used by a Mesh on import. First, the importer looks for a sub-folder called Textures within the same folder as the Mesh or in any parent folder. If this fails, Unity performs an exhaustive search of all Textures in the Project. Although slightly slower, the main disadvantage of the exhaustive search is that there could be two or more Textures in the Project with the same name. In this case, it is not guaranteed that Unity can find the right one.
Place your textures in a Textures folder at or above the asset’s level
(A) Possible places to find Textures
(B) Mesh being imported
Material generation and assignment
If you choose Standard or Import via MaterialDescription (Experimental) from the Material Creation Mode drop-down menu, and choose Use Embedded Materials from the Location drop-down menu, Unity does the following:
For more information, see the Materials tab reference page.
Colliders
Unity uses two main types of colliders: Mesh Colliders and Primitive Colliders. Mesh Colliders are components that use imported Mesh data and Unity can use them for environment collision. When you enable Generate Colliders on the Model tab, Unity automatically adds a Mesh collider when you add the Mesh to the Scene so that the physics system considers it solid.
If you are moving the GameObject around (a car for example), you cannot use Mesh colliders. Instead, you will have to use Primitive colliders. In this case you should disable the Generate Colliders setting.
Animations
You can import animations from a Model file. Follow the guidelines for exporting FBX files from your 3D modeling software before importing it into Unity.
Normal mapping and characters
If you have a character with a normal map that was generated from a high-polygon version of the Model, you should import the game-quality version with a Smoothing Angle of 180 degrees. This prevents odd-looking seams in lighting due to tangent splitting. If the seams are still present with these settings, choose Calculate Legacy With Split Tangents from the Tangents drop-down menu. If you are converting a greyscale image into a normal map, you don’t need to worry about this.
Blend shapes
For information about how to import blend shapes into Unity from 3D modeling applications, see the documentation for the Model tab of the Model Import Settings window.
Hints
Merge your Meshes together as much as possible. They should share Materials and Textures as much as possible. This has a huge performance benefit.
If you need to set up your GameObjects further in Unity (adding physics, scripts or other components), make sure you name your GameObjects properly in your 3D application. Working with names like pCube17 or Box42 can be very difficult.
Center your Meshes on the world origin in your 3D modeling application. This makes it easier to place them in Unity.
If a Mesh does not have vertex colors, Unity automatically adds an array of all-white vertex colors to the Mesh the first time Unity renders it.
The Unity Editor shows too many vertices or triangles (compared to the original Model in your 3D modeling application).
This is correct. What you are looking at is the number of vertices/triangles actually being sent to the GPU for rendering. In addition to the case where the Material requires them to be sent twice, other things like hard-normals and non-contiguous UVs increase vertex/triangle counts significantly compared to what a 3D modeling application tells you. Triangles need to be contiguous in both 3D and UV space to form a strip, so when you have UV seams, degenerate triangles have to be made to form strips, which bumps up the count.
Анатомия мешей
Меш состоит из треугольников, расположенных в 3D-пространстве так, чтобы создать впечатление замкнутого объекта. Треугольник определяется тремя угловыми точками или вершинами. В классе Mesh, все вершины хранятся в одном массиве и каждый треугольник задается с помощью трех целых чисел, которые соответствуют индексам в массиве вершин. Треугольники, также, собраны в единый массив целых чисел, которые берутся группами по три от начала этого массива, так чтобы элементы 0, 1 и 2 определили первый треугольник, 3, 4 и 5 определили второй, и так далее. Любая вершина может быть повторно использована во многих треугольниках по желанию, но есть причины, когда это может быть нежелательно, что объясняется ниже.
Освещение и нормали
Треугольников достаточно, чтобы определить основную форму объекта, но в большинстве случаев необходима дополнительная информация для отображения сетки. Чтобы объект был правильно затенен при освещении, для каждой вершины должен быть указан вектор нормали. Вектор нормали направлен наружу перпендикулярно поверхности сетки в положении вершины с которой он связан. При расчете затенения, каждая нормаль к вершине сравнивается с направлением падающего света, который также вектор. Если направления этих векторов параллельны, то поверхность получает свет в лоб в этой точке и полная яркость света будет использоваться для затенения. Свет, приходящий точно перпендикулярно вектору нормали не даст освещения поверхности в этой точке. Как правило, свет падает под углом к нормали и поэтому затенение будет где-то между полной яркостью и полной темнотой, в зависимости от угла.
Так как сетка состоит из треугольников, может показаться, что нормали на его углах будут точно перпендикулярны плоскости их треугольника. Однако на самом деле нормали интерполируются между треугольниками с получением среднего значения между соседними углами. Если все три нормали треугольника указывают в одном направлении, то треугольник будет равномерно освещен на всем протяжении. Эффектом того, что разные треугольники равномерно затенены будет то, что края будут очень четкими и отчетливыми. Это именно то, что требуется для модели куба или других объектов с острым краем, но интерполяция нормалей может быть использована для создания плавного затенения, чтобы представить изогнутую поверхность.
To get crisp edges, it is necessary to double up vertices at each edge since both of the two adjacent triangles will need their own separate normals. For curved surfaces, vertices will usually be shared along edges but a bit of intuition is often required to determine the best direction for the shared normals. A normal might simply be the average of the normals of the planes of the surrounding triangles. However, for an object like a sphere, the normals should just be pointing directly outward from the sphere’s centre.
Вызывая Mesh.RecalculateNormals, вы можете поручить Unity рассчитать нормали для вас, сделав некоторые предположения о “смысле” геометрии сетки; она предполагает, что вершины общие для нескольких треугольников обозначают гладкую поверхность в то время как удвоенные вершины указывают на четкие края. В большинстве случаев это не плохое приближение, однако RecalculateNormals будет спотыкаться в некоторых ситуациях текстурирования, когда вершины должны быть удвоены, хотя поверхность гладкая.
Текстурирование
Подобно нормалям, текстурные координаты уникальны для каждой вершины и, таким образом, существуют ситуации, когда приходится дублировать вершины для получения различных UV значение вдоль ребра. Очевидный пример, это когда два соседних треугольника используют разделенные части текстуры (например, глаза на текстуре лица). Также, большинство полностью замкнутых объемов потребуют “шов”, где область текстуры заворачивается, и соединяется. Значения UV на одной стороне шва будут отличаться от тех, что на другой стороне.