- Home /
Vertex count on a procedurally generated map and some related doubts
Hello everyone.
Yesterday I posted a question about having problems with unity crashing while my map generation being executed. I was told not to instantiate that large number of cubes from an array and instead merging all the tiles in a single mesh. After some research on how unity works with meshes generated by code (using the mesh class) and how are some famous games which need to handle a large number of tiles or blocks in 3d (i.e. Minecraft) I've started working. First with a small cube, adding UV mappings, then creating simple meshes in some patterns...
After all this, I thought it's time to start implementing what I need for my game, as it didn't seem that difficult on the first place. I have a large array of cubes, each array tile stores the desired tile texture I need to use for that single tile, as well as many other information. But I'm having some trouble trying to figure out on how to implement this the right way. (To be more clear and make it short, I want to show on screen a large array of tiles that the user will be then able to interact with, but not modify).
First of all, some limitations I didn't have before came into mind. I'd like to ask those questions first:
If i want to create the whole mesh block by block, it seems reasonable to keep storing data to the vertices array until I've finished creating all the blocks (or tiles) for the map, and then do the same for the triangles and UV mapping array, this would work just fine if I could keep adding data to the array, but to initialise an array I need its size. What first came into mind was to first store the values into a resizeable list (generic class list, from the .net libraries) and when I'm done passing the values to an array. The other method, is to calculate the total vertex count for the mesh before actually creating any vertices, but that seems more costly than the first method.
Then I thought about the normal maps, and all the other shading effects. If I can only use one material per mesh, how I am supposed to render each tile as I want to?
Also I've seen the method Mesh.CombineMeshes(), would that be of any use for what I'm trying to accomplish here?
Thanks in advance
So after my auto answer, to make this more clear, I'm still interested into the first point (How to know how many vertex there will be if possible), and what about the $$anonymous$$esh.Combine$$anonymous$$eshes() method, as it might prove useful for what I'm trying to do.
Yes, I figured out that, what I wasn't able to figure out at first was how to render each tile differently, not how to use different textures. I see my question wasn't really clear. I should spend more time writing the questions...
But thank you anyway ^^
Answer by Eric5h5 · Dec 29, 2012 at 11:12 AM
Are you sure you need different materials? You could just use one material and a texture atlas, then UV map the cubes as appropriate. You're not going to be able to create a single mesh for the entire world though, unless it's quite small, since meshes use 16-bit indices and therefore have a limit of 65534 vertices per mesh (should be 65536 but for some reason it's 2 bytes less). It should be trivial math to calculate the number of vertices in advance, so there's no particular reason to use generic Lists for this, especially since they are slower than arrays. It would be more efficient to create the meshes yourself, so the Combine function in Unity isn't really appropriate here.
I guess the reason to have different materials would be so that certain tiles could have a different shader - but of course it would be best to still batch those together based on shader.
Yes, that's what $$anonymous$$e craft did as well. They basically use 2 different materials and split the mesh on these. One opaque and one transparent. This is also important for "occlusion-culling" to deter$$anonymous$$e which face of which cube needs to be drawn.
They still use one single texture for the whole terrain to keep the draw calls low:
http://img7.imagebanana.com/img/3fziwvhm/terrain.png
$$anonymous$$eep in $$anonymous$$d each material means another draw call.
as @whydoidoit said, the reason for having more than one material is being able to render different tiles in different ways. $$anonymous$$aybe I would want specular reflection on a metallic floor and diffuse reflection on a grass floor. I didn't say I would be using one material per tile, I was rather thinking on having one material per render-type tile, so all the normal mapped tiles with diffuse reflection would be made of the same material. I don't know what do you exactly mean by texture Atlas, but I imagine you're talking about having all the tile textures on the same image file and specify which one to use by coordinates. That's exactly what I was planning to do.
And to answer @Fattie and @Eric5h5, I didn't know that limiation and I would need to do something about it. I'm not planning on any maps larger than 100x100 (just one layer) anyway, but I want to make it as flexible and professional as I can, so I'll have to think on something similar to the chunk system in $$anonymous$$ecraft (yeah.. $$anonymous$$ecraft again xD).
Also, about the vertex limitation. As I'm planning on an static mesh, I'm not even planning to include in the mesh all the vertices that won't be rendered, so it's not as easy as number of tiles * 6 to get the total number of vertices. To get it accurately I have to check tile by tile, and check the neighbours, That seems a little bit more costly to me. This might be a performance vs memory thing? Or I'm completely wrong and it's much faster to do the previous calculations?
Yes a texture atlas is a combination of all of the textures for the models - you can build that internally to the game using Texture2D.PackTextures or do it before time.
Setzer -- one point -- to be clear:
Do you mean you're only doing this ONCE, AT THE LAUNCH OF THE LEVEL?
And then it just sits there?
IF THAT IS WHAT YOU $$anonymous$$EAN: there is good news in that you have no performance concerns at all, in terms of building it.
(You seem to be discussing this in the recent, sorry if I misunderstand you.)
Any one of dozens of normal, everyday actions by the amazingly complicated hardware-software pipeline you are dealing with with utterly dwarf anything you are doing. (Like "loading the splash screen" or "Cocoa getting fonts ready" or "Audio decompression for your chip-style background music" will dwarf anything you're doing here.)
Notice this Tolstoy-length discourse for example on doing things DURING PLAY versus at start up time, it is a different universe of considerations
http://answers.unity3d.com/questions/315059/how-to-improve-performance-while-generating-extrud.html
somewhat related ..
http://answers.unity3d.com/questions/321428/adding-mesh-collider-in-run-time-slow.html
So IF that is the case, it's all good news - you can forget it and get to work!!
Answer by Setzer22 · Dec 28, 2012 at 11:01 PM
After a lot of trial and error, I'm going to auto-answer me some of my doubts.
I've found out that to have more materials in a single mesh, you can create submeshes, each submesh with a different material. To add submeshes to a mesh, first one needs to set up the number of submeshes with the Mesh.submMeshCount property. Once it's done, you can add groups of triangles to the mes with the Mesh.SetTriangles method, note that, although you might have set the count of meshes to 2, they start indexing from zero, and assigning a submesh to an index larger than subMeshCount will not provide the desired result.
So, this subMesh thing answers one (and a half) of my questions. I'm looking forward to see if someone can give me a hand with this. Meanwhile I'll keep trying and searching. For the simple stuff, like instantiating projectiles, the Unity documentation might seem like the most accurate and well-designed wiki, but to be honest, I wasn't able to find many of this simple information I was looking for easily there, and even if I found it, I wasn't able to figure out what to do until I went outside to look for some examples.
PD: I know this isn't a full answer, but I thought it fitted more into the answers than into a comment, as it actually answers something.
Your answer
Follow this Question
Related Questions
Procedural mesh creation issue 1 Answer
Colors do not work with a mesh created in script? 3 Answers
Trouble recalculating 3D mesh's triangles after deleting verts 2 Answers
minimize vertex artifacting for procedural mesh manipulations - vertex collision same object? 0 Answers
using grayscale texture as heightmap, vertices and pixel don't match 0 Answers