Is it me or is the code example of the meshcombiner ( Unity - Scripting API: Mesh.CombineMeshes ) flawed?
Er…yeah, if by “flawed” you mean “can’t possibly work and won’t even compile”… Here’s some actual working code:
// This script should be put on an empty GameObject
// Objects to be combined should be children of the empty GameObject
@script RequireComponent(MeshFilter)
@script RequireComponent(MeshRenderer)
function Start () {
for (var child in transform)
child.position += transform.position;
transform.position = Vector3.zero;
transform.rotation = Quaternion.identity;
var meshFilters = GetComponentsInChildren(MeshFilter);
var combine : CombineInstance[] = new CombineInstance[meshFilters.Length-1];
var index = 0;
for (var i = 0; i < meshFilters.Length; i++)
{
if (meshFilters[i].sharedMesh == null) continue;
combine[index].mesh = meshFilters[i].sharedMesh;
combine[index++].transform = meshFilters[i].transform.localToWorldMatrix;
meshFilters[i].renderer.enabled = false;
}
GetComponent(MeshFilter).mesh = new Mesh();
GetComponent(MeshFilter).mesh.CombineMeshes (combine);
renderer.material = meshFilters[1].renderer.sharedMaterial;
}
(It’s stuff like this which makes me wonder why in the world GetComponentsInChildren doesn’t do what it says, and return components in the children only… Seems like that trips me up almost every time.)
–Eric
Thanks a bunch!
This code simply will not work for me. The game objects being combined simple disappear. I will keep experimenting but I have removed all other scripts on the base empty object. Any ideas?
It appears the code you added to compensate for the empty game object NOT being at 0,0,0 did not work.
I tested it several times and it works fine.
–Eric
Works fine!
Was trying out the documentation provided by unity and was getting frustrated… Found this thread with actual working code!
It’s probably because your combined version of your meshes exeeds the limit of 65 k. vertices. I know I have had that at some point.
That’s likely it - I gave up on it as it never worked for me in most cases.
Doesn’t look like this works with a submesh.
Any idea’s?
I tried adding the following in the for loop:
combine[index].mesh.subMeshCount = meshFilters[i].mesh.subMeshCount;
combine[index].mesh.SetTriangles(meshFilters[i].mesh.GetTriangles(0),0);
combine[index].mesh.SetTriangles(meshFilters[i].mesh.GetTriangles(1),1);
and the following at the end:
GetComponent(MeshFilter).mesh.subMeshCount = 2;
My mesh only has 2 submesh.
I’ve got a similar problem where i’m generating meshes via code. Making a single one works, but running it through a loop where each loop adds to a CombineInstance, which is added to a single mesh at the end of the method, returns an empty mesh…
The final/returned mesh has the correct amount of verts+tris.
Can you post the code you are using, Duke?
I’m getting the same behavior. Is this a GPU issue, or something else I’m missing?
I think I solved it. If you apply this to existing meshes (i.e - they were in the scene before you applied the script to the parent object), it won’t work and your meshes will disappear. You will have to rebuild the hierarchy of meshes again, unfortunately.
A clear explanation of this would be:
A/Place this code on a parent object with meshes already in it
B/Place in object where clones will appear
C/place above cloning script
D/Place below cloning script
E/Place in seperate parent object to cloning script’s gameobject
F/Place limit of 65k vertices for every combinemesh script.
G/Parent requires Mesh Filter
H/Clone script requires Mesh Filter
It failed for me and i have all those questions that i cant find and answer for, any help is welcome.
I realize this is an old thread, but… is there any way to preserve the lightmapping on the meshes that are combined? Some trick I’m missing? I’ve verified the UV’s are copied over correctly, however, the lightmaps render with the incorrect mapping.
I’m sure it’s because the empty parent object doesn’t have the proper lightmap index set up and the atlas tiling and offset information… and if the lightmap scale had been changed on any of the child objects?
I can manually fiddle with the atlas tiling and offset for the parent and get one of the objects to look right…
Does this mean I have to manually remap all the lightmap UV’s to get this to work and if so, how come CombineMeshes doesn’t automatically do this?
For anyone that happens along this thread… I figured out the questions I asked above.
You do have to remap the lightmap uvs yourself if you’re hoping to combine already lightmapped objects.
First create the new, empty game object with the lightmapIndex set properly ( if you’re using multiple lightmaps, you’ll have to combine objects using only the same lightmap index ), set the lightmapTilingOffset to Vector4( 1.0f, 1.0f, 0.0f, 0.0f ). And then for each mesh you are combining, modify the mesh.uv2 elements to adjust for the fact that there is no longer a gameobject they are tied to that provides the proper lightmapTilingOffset to the renderer. That code will be something like this:
// remap the lightmap uvs before combining
Vector2[] uvs = mesh.uv2;
Vector4 lightmapTilingOffset = meshFilter.renderer.lightmapTilingOffset;
// remap the uvs to adjust for the parent objects lightmap tiling and offset values
Vector2 uvscale = new Vector2( lightmapTilingOffset.x, lightmapTilingOffset.y );
Vector2 uvoffset = new Vector2( lightmapTilingOffset.z, lightmapTilingOffset.w );
for ( int j = 0; j < uvs.Length; j++ ) {
uvs[j] = uvoffset + new Vector2( uvscale.x * uvs[j].x, uvscale.y * uvs[j].y );
}
mesh.uv2 = uvs;
Additionally, if you’re using negative scale on any of the objects to flip them in the scene ( evident by them drawing inside out in your scene now ), then you’ll want to flip the winding order of the verts in all of the triangles for that individual mesh.
It would be nice if in a future version of the engine, CombineMeshes did these steps for us.
-andrew
Thanks MrScary … this helps but the gotcha I found was I need to run a light mapping pass on the scene before the combine or the offsets will be useless.
Right… what are you trying to do? In my case, I was taking a lot of small meshes and combining them into bigger ones to reduce object counts. The lightmaps have to be baked first. It’s possible that you could check the “lock atlas” toggle in the light mapping window and rebake afterwards, but I wouldn’t hold your breath.
Another nugget for anyone else who comes across this. We were having the same problem as MrScary, but our situation was slightly different. In our case we were taking a prefab that was made from several meshes and using CombineMeshes to create a prefab with a single mesh.
In our instance, the meshes which had their .uv2 set all had their lightmaps come out wrong, the meshes which did not have any uv2 (i.e. set to null) were correct when a light pass was done. So I had to make sure there were no uv2 values set after combining the meshes.