- Home /
Can a mesh vertex have multiple materials?
Hello Unity gurus!
I have a complex mesh in Blender that features 10+ different materials that I'd like to render as-is in Unity.
For technical reasons I must stream the mesh from Blender to Unity but unfortunately Blender's ability to have a single vert map to a number of materials (each having different uv) doesn't appear to be possible with Unity...
Which is odd because if I import the same mesh into Unity via FBX and the Unity editor it will render beautifully without seams between the textures without adding any verts.
Currently the only way I was able to make this work was to manually split the vertices in Blender to enforce one-vert-per-uv and if I adjust the normals at the split verts then everything looks perfect but this is complex and expensive.
Since the Unity importer can make this work without splitting verts is there a way to programmatically accomplish the same via C#?
Thanks so much for a hint in the right direction! That one got me stumped!! :-)
Answer by Bunny83 · Sep 21, 2017 at 12:05 AM
Vertices are not linked to any material, only triangles are. A normal mesh has only a single material and a single "triangles list". However a mesh can have multiple "submeshes". That means the mesh uses the same vertices but seperate index lists, one for each submesh.
However keep in mind that all vertex attributes stay the same for all submeshes. So you can't have different UV0 coordinates on the same vertex for different materials. If you need this the vertex has to be splitted. Unity does this automatically on import. In general if any vertex attribute is different for two triangles which share that vertex it has to be splitted, even when both triangles use the same material / blong to the same submesh. That's why a cube has 24 vertices instead of 8 since each side need to have it's own normal. Since each of the 8 corners are shared by 3 different sides you need 8*3 == 24 vertices.
To manually set the triangles for a submesh you first have to set vertices, then the subMeshCount to the number of submeshes you have and finally use SetTriangles for each submesh index to define the triangles for each submesh.
The used MeshRenderer need to have as many materials as there are submeshes in the mesh. The order is the same. So submesh0 uses the material at index 0.
Hi Bunny83!
Thank you very much for the expert information!
It turns out that I've been using this method (with 'sub$$anonymous$$eshCount' and SetTriangles()) in the past and I get perfect results if I set normals to the split verts the same.
So to confirm... I guess there is no other way to do it eh? Split verts are indeed a must?
If so it is just so odd that the Unity importer makes this happen without adding verts... perhaps it does split the verts but adds an order of indirection so that the C# code can still refer to the mesh using the original (smaller) mesh indices?
Thanks again!! :)
No, the Unity importer can't import a mesh without splitting vertices if it's necessary. For example if you calculate normals on import there's a smoother angle you specify. If you set it to "0" you want sharp edges everywhere. So if the original mesh had shared vertices everywhere you will end up with more vertices in Unity.
Actually many artists have experienced this behaviour and were suprised why after importing the mesh it has more vertices than in their modelling application. Such as this, this, this, this, this, this and this.
Hi again Bunny83,
Thanks for the prompt and usable answers! Helps me in my day! I appreciated all the links and have read most of that. I guess I will continue using my current sub$$anonymous$$eshCount and SetTriangles() with shared normals and try to make things faster if I can.
Answer accepted! Have a great day! :)