Saturday, 15 February 2014

Regarding Meshes in Unity

Maybe it's just my OpenGL (1.1) background but here's a few roadblocks I've hit while doing procedural Mesh generation in Unity, along with a few tips not many people seem to know of. Some of this knowledge has been useful even outside my procedural experiments.

Quick Overview (stuff you really should know)

  • You will read this until your eyes bleed
  • Mesh.vertices contains your vertices. Mesh.triangles contains indexes to the vertices array. 
  • Normals (and UVs) are per Vertice. E.g.: Mesh.normals[i] has the normal for Mesh.vertices[i] (Blender uses normals for each face, which sometimes confuses people)
  • Different materials means different submeshes (or a new Mesh if that's what you're into).

A few pitfalls and tips

  • Mesh.uv1 != Mesh.uv (WHY AREN'T MY TEXTURE COORDINATES DOING ANYTHING?)
  • If your mesh has more than  one material, you have to use submeshes to define which area has a certain material. When copying meshes, I've found that I have to manually SetTriangles() as no other way of copying submeshes seems to work.
  • The backface is determined by the order of the vertices in each triangle, NOT its normal. If your mesh looks like it's inside out this is probably why.
  • Some of Unity's built-in shaders (namely the bump mapped ones) do not calculate their own tangents. Each Mesh has their own tangent array for this specific purpose. Unfortunately they can't be auto-calculated.
    • Blender files do not have these by default but fortunately Unity can calculate them automatically. Sadly, we don't have access to their algorithm for this.
    • Fortunately there's some code floating around that works. 
  • Don't generate a new Mesh() every time. Use the same mesh instance and .Clear() it. New meshes will get fed to the GPU but won't replace the old data there, causing memory leaks.
  • 99% of the time you can just call Mesh.RecalculateNormals() at the end instead of reinventing the wheel and calculating your own normals. As far as I know this calculates the normals based on the order of the vertices. 
  • Don't forget to Mesh.RecalculateBounds() if having decent bounds is important to you.
  • When you add a collider Unity will automatically fit it to the current Meshfilter's bounds.