Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
This question was closed Feb 14, 2016 at 02:44 PM by joshua-lyness for the following reason:

The question is answered, right answer was accepted

avatar image
0
Question by joshua-lyness · Feb 13, 2016 at 08:14 PM · errorcombinemeshesexistscombineinstance

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 ;)

 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[i].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[i].transform = tree.GetComponent<MeshFilter> ().transform.localToWorldMatrix;
             Destroy (tree.gameObject);
             //disables the mesh renderer (commented out for experimentation purposes)
             //tree.GetComponent<MeshRenderer>().enabled = false;
             //increments i for the array location
             i ++;
         }
         //does the same process to the existing mesh (adds it to the combine instance
         toApply[i].mesh = filter.mesh;
         toApply[i].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 ;)

Comment
Add comment · Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image joshua-lyness · Feb 13, 2016 at 08:20 PM 0
Share

Oh and another thing you might be able to help me with, is it only works up to the vertices limit of 67,000. anyone know the most concise way of checking its size and then making a new mesh (submesh?) thanks

avatar image joshua-lyness joshua-lyness · Feb 13, 2016 at 08:37 PM 0
Share

ahhh don't worry, figured it out. All you gotta do is have a mesh array, pretty simple if you learn how to google properly xD

avatar image joshua-lyness · Feb 13, 2016 at 10:24 PM 0
Share

Ok so I assume whats happening is the mesh is being referenced back to the individual trees mesh. So that means every frame its combining the same objects?? this must destroy performance?? Does anyone know a way I can make the mesh independent? Or have I got this all completely wrong? I literally don't know what I'm doing....

avatar image joshua-lyness · Feb 14, 2016 at 01:54 PM 0
Share

Ok so if I add a cube to the joined mesh and run it, the cube mesh is deleted. So it must combine all the objects in the array and then replace the mesh in it, as opposed to adding to the current mesh. However I cant use the current mesh in the array or I get that error, nobody can help? :(

1 Reply

  • Sort: 
avatar image
0
Best Answer

Answer by joshua-lyness · Feb 14, 2016 at 02:43 PM

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

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image string_username · Mar 07, 2017 at 09:32 AM 0
Share

What line?

avatar image joshua-lyness string_username · Mar 12, 2017 at 06:24 PM 0
Share

Trying to understand what I was trying to do above is impossible. Now that I have some more experience, I'll explain. Say you have an array of meshes you want to combine together (or maybe just a couple $$anonymous$$esh variables, same applies.) In my case, I have a for loop that generates a mesh from a Bezier Curve. This here is where I apply the vertices, faces, normals, and UV's.

 mesh[curveIndex] = new $$anonymous$$esh();
 mesh[curveIndex].vertices = verts;
 mesh[curveIndex].normals = normals;
 mesh[curveIndex].triangles = triangles;
 mesh[curveIndex].uv = uvs;

Now I made a combine instance before the for loop, which you set to be as long as the number of meshes you want to combine.

 CombineInstance[] combineInstance = new CombineInstance[length];

The combineInstance type has few properties that need to be assigned. The mesh, and the position relative to world space. Otherwise the meshes wont know where they need to be, relative to one another. When you think about it, the only way a mesh knows where to draw is the position of the vertices, which are all relative to world space. You just need to tell the CombineInstance that the vertices are relative to world coordinates.

 combineInstance[curveIndex].mesh = mesh[curveIndex];
 combineInstance[curveIndex].transform = buildGameobject[roadIndex].transform.localToWorld$$anonymous$$atrix;

It's that transform.localToWorld$$anonymous$$atrix that's important. I've never had a case where it's not been local to world positions. If you just want to combine a few meshes in your scene to one object for performance reasons, and you dont want the meshes to move, then localtoworld is your friend.

Once you have specified every mesh and transform of the combine instance (the submesh indexes too if you need to use them), then you can combine! Essentially, this is the point your code turns the combineinstance into a mesh, and puts it in a variable.

 buildGameobject[roadIndex].GetComponent<$$anonymous$$eshFilter>().mesh.Combine$$anonymous$$eshes(combineInstance, true, true);

The (..., true, true) bit for me isnt really relevant, since I have no submeshes, and I always make sure usematrices is true, since I want the combineInstance to use the transform positions I gave it earlier.

I'm not great at explaining, but heres a couple links to documentation that unity provides. https://docs.unity3d.com/ScriptReference/$$anonymous$$esh.Combine$$anonymous$$eshes.html https://docs.unity3d.com/ScriptReference/CombineInstance.html

Remember :

     1 : $$anonymous$$ake combineInstance()
     1.5 : Get the meshes
     2 : Put the meshes in combineInstance[].mesh
     3 : Set combineInstance[].transform to mesh.transform.localToWorld$$anonymous$$atrix
     4 : Finally, final$$anonymous$$esh.GetComponent().mesh.Combine$$anonymous$$eshes(combineInstance, true, true)

I hope this has helped, I tried anyway :D

avatar image joshua-lyness string_username · Mar 18, 2017 at 09:22 PM 0
Share

Hey string username, I know youve tried adding comments to this, but for whatever reason they won't show up. $$anonymous$$ake a new question and tag me in it, and ill try to help.

Follow this Question

Answers Answers and Comments

40 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Apple LLVM 9.0 Error, Unable to execute command: Killed:9 0 Answers

Setting button intractability causes an error 1 Answer

Unity broken, hangs at "Loading..." screen. Help! 1 Answer

can someone help me out what is wrong in this code? 0 Answers

please tell me about the error popped during building my project for android platform,please tell me about this error :: 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges