Combine Meshes combine with current mesh

Ok so I have a tree script that generates trees in a random location within a circle. To stop the trees from generating ontop of each other, when the raycast to generate the tree is fired downwards, if it collides with the tree collider it will re-raycast until it finds a point without an exisiting tree.
For performance reasons I needed to merge the tree meshes together (each tree was making 3 draw calls, one for shadow, one for the light, and one for the object itself) and with up to 40^2 trees placeable, was making waaaaay too many batches.
So long story short I made a mesh merge script that gets the mesh from every object with the tag “firTree” and then put those into the combineInstance variable. Then I use the combineMeshes function to put that into an empty gameObjects mesh filter, and disable all of the meshRenderers of the individual trees.
Heres the Problem:
Whats going on is every frame it is getting the mesh data from the individual trees and combining them. If I was to make thousands of trees, the fps would die from merging all of them every frame. Therefore I wanted to Destroy() the individual trees once they had been combined, however the trees disappear. So…I made another combineInstance slot in its array for the current combined mesh, so that what would happen is it would combine, then destroy the original objects, and only combine new trees. However Unity throws up the error :

Cannot combine into a mesh that is also in the CombineInstances input: 5,0_firTree
UnityEngine.Mesh:CombineMeshes(CombineInstance[], Boolean, Boolean)
meshMerge:Update() (at Assets/treeTool/firTree/meshMerge.cs:50)

so I assume that means it is already combining it to the current mesh?? but if so then why do the trees disappear when I destroy the individual ones? They should still be visible after I remove the original mesh data, right? Or does it need to continue referencing it? I don’t even know what unity is doing xD

Anyway, just in case its helpful, ive got the combine script. If you are going to run it, remember to tag your objects as “firTree” for it to work :wink:

using System.Collections;

public class meshMerge : MonoBehaviour {

	//the meshFilter of the combined tree object
	private MeshFilter filter;

	//the meshFilter array of gameObects to combine
	private Component[] meshFilterArray;

	//objects to combine 
	public GameObject[] toCombine;

	//the mesh instance to apply, special type for meshcombine function
	public CombineInstance[] toApply;

	void Start () {

		//sets combined filter to the current mesh filter (for reference optimisation)
		filter = GetComponent<MeshFilter>();

		//makes a plain mesh, with no current data (for merging purposes)
		//there always needs to be a mesh in this location, otherwise when merging, the first time will generate
		//an error for no current mesh to combine with
		filter.mesh = new Mesh();

	void Update () {
		//will put all gameObjects with the tag firTree in the array of gameObjects to combine
		toCombine = GameObject.FindGameObjectsWithTag ("firTree");
		int i = 0;
		//the combine instance for the combineMeshes, sets length to the gameObject array,  +1 for existing mesh 
		toApply = new CombineInstance[toCombine.Length + 1];
		//repeats for every gameObject
		foreach(GameObject tree in toCombine){
			//passes in the mesh data
			toApply*.mesh = tree.GetComponent<MeshFilter> ().mesh;*
  •  	//converts the local positions to world positions in a matrix, so the combineMesh can use it (no idea why)*

_ toApply*.transform = tree.GetComponent ().transform.localToWorldMatrix;_
Destroy (tree.gameObject);_
//disables the mesh renderer (commented out for experimentation purposes)_
//tree.GetComponent().enabled = false;_
//increments i for the array location*_
* i ++;*
* }*
* //does the same process to the existing mesh (adds it to the combine instance*
_ toApply*.mesh = filter.mesh;
toApply.transform = filter.transform.localToWorldMatrix;*_

* //joins all meshes, set other parameters to true so it uses the matrix positions and make them a single mesh*
* filter.mesh.CombineMeshes (toApply, true, true);*
* }*
if you can enlighten me as to what I’m doing wrong, I’m very grateful. Thanks :wink:

Hmm I figured it out myself. All that I needed to do was add a line before combining, to make a new mesh. So:
filter.mesh = new mesh();

that way I wasn’t writing to a mesh I had just read from, no idea why unity doesn’t let you do that. If anyone could explain that would be great, but otherwise, its sorted.

Oh and a little tip if anyone uses my code, don’t delete the destroy part in the foreach, otherwise the mesh size increases exponentially and causes unity to crash xD