- Home /
Modifying Sub-Meshes at Runtime & MeshRenderer
I've been working on creating meshes in code, and ran into a hitch.
When modifying the subMeshCount, and then reassigning the corresponding materials on the renderer, very strange things happen if I am working with an existing mesh object.
I'm calling mesh.Clear(), modifying the subMeshCount, and reassigning all verts, and triangles, etc. I am then updating the MeshRenderer materials array.
However, unless I destroy the MeshRenderer and then re-add it, the displayed mesh is not correct, that is, it isn't the same mesh I've modified (proven by querying the mesh in code). Is this expected behavior, or a bug? Has anyone successfully modified the subMeshCount (from 1 to 3 or more) of an existing mesh at runtime, and lived to tell the tale?
Up until this point, modifying meshes from code has worked pretty well, but when modifying the subMeshCount, the rendering explodes, short of my 'hack' described above.
--Here is the working code, without destroying and re-adding the MeshRenderer, odd things ensue:
private void ResetSubMeshLength(){
myMesh.Clear();
myMesh.subMeshCount = myMaterials.Length;
AddRenderer(); //Without this function, hilarity ensues...
meshRenderer.renderer.materials = myMaterials;
InitializeTriangles(); //creates triangle holder, extends array
BuildTriangles(); //init an ArrayList for each subMesh group of tris
UpdateMesh(); //add verts, triangles, etc...
}
private void AddRenderer(){ if(meshRenderer){ DestroyImmediate(meshRenderer); }
gameObject.AddComponent(typeof(MeshRenderer)); meshRenderer = (MeshRenderer)GetComponent(typeof(MeshRenderer));
}
and the update mesh function, just fyi....
public void UpdateMesh(){
// Have all existing sprites re-apply their data
foreach(UISprite sprite in UISprites) {
sprite.AddToMesh(); //gets each quads data - updates arrays
}
myMesh.vertices = theVertices;
myMesh.uv = theUVs;
myMesh.colors = theColors;
//better to find a way to use int[] directly, this is tedious and slow
for(int i = 0; i< totalTriangles.Length; i++){
int tricount = totalTriangles[i].triangles.Count;
int[] tris = new int[tricount];
for(int j=0; j<tricount; j++){
tris[j] = (int)totalTriangles[i].triangles[j];
}
myMesh.SetTriangles(tris,i);
}
myMesh.RecalculateBounds();
}
Answer by TOROPOT · Dec 02, 2010 at 12:23 PM
I have the same problem.
It's seems the mesh was confused with new order of triangles list with set 0 and set 1 when "subMeshCount" was modified in runtime.
For example, if material 0 use int[] a0 for SetTriangles( a0, 0 ); material 1 use a1 as SetTriangles( a1, 1 ); material 2 use int[] a2 for SetTriangle( a2, 2 ); and then if material 1 was no longer use, reset subMeshCount into 2, SetTriangle( a0, 0 ); SetTriangle( a2, 1 ); the mesh will treat a2 as a0.
My soultion is DestroyImmediate() meshRender component only, re-add new MeshRenderer when the count of Materials had been changed.
This is the situation "confused" Triangles' list, the Triangle index list of material 1 was mistook into material 0 (Wood boards were combined with Jewels in stranged error way.):
These are materials what I used, the material 2 (AFRO men) was new added one, then bug happened:
This is correct sprites situation, if I DestroyImmediate() old MeshRender and creat new one MeshRender when every time the count of materials had changed ( but nothing else of codes changed ):
As I said above, mesh mess up and confused the sets of int[] of Triangles using in SetTriangles().
Answer by andeeee · Jan 22, 2010 at 11:19 AM
There are a few places in Unity scripting where an object needs to be recreated or reassigned to get the right behaviour. However, you should ideally get an error message or it should fail silently. When you say this "explodes", do you mean a crash, bizarre rendering artifacts or... what?
Very strange rendering artifacts, as in some geometry simply isn't drawn. And yes, it fails entirely silently. Basically, if this is an issue, that array length (of materials) should not be modifiable at runtime.