• 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 /
avatar image
0
Question by thijsdaniels89 · May 30, 2013 at 11:13 PM · meshproceduralvoxelcombine

Could anyone tell me what's wrong with my voxel rendering?

Hey there! I'm making a 2.5D platformer game that uses 3D tiles (basically voxels) and quickly ran into performance issues. With around 30k draw calls and 500k triangles (95% percent of which are unnecessary) I really need to change something :p So I read up quite a bit on voxel engines, made chunks (10x10x10) and let each chunk deal with its voxels like this:

  • The voxels are placed by hand, so instead of being generated, they are scanned, aligned and then indexed on game start. The result is the same, though: the world consists of a 3d array of chunks, each containing a 3d array of voxels.

  • Voxels that are entirely surrounded by other voxels are then disabled altogether.

  • All the remaining voxels' meshes are cleared and only the faces that are next to empty space are re-added to the mesh.

This all works, but I still have to combine all the meshes that are the same. Of course, i've been googling around and almost everyone advised to use the CombineChildren script, disabling it by default and then enabling it after the chunks have done their thing, but when I enable the script at the end of the chunk's scripts, the game crashes. Is there another way to combine an object's children's meshes?

My second question is whether I should already notice a major improvement in the performance, even without combining the meshes. unfortunately, im actually getting a longer rendering time per frame at the moment (about 30% longer). This makes sense because i'm also getting an increase in draw calls, but... should i be getting an increase in draw calls, or am i doing something horribly wrong? I do get about a 90% reduction in tris and verts, though, so i guess at least that part of my code works xD

Here is the function i made that deals with generating the mesh of a single voxel:

 function GenerateMesh(block: GameObject, position: Vector3) {
     
     // clear old mesh
     var meshFilter: MeshFilter = block.GetComponent(MeshFilter);
     meshFilter.mesh.Clear();
     
     // make vertices
     var size = 0.5;
     var vertices = [
         Vector3(-size, -size, -size),
         Vector3(-size,  size, -size),
         Vector3( size,  size, -size),
         Vector3( size, -size, -size),
         Vector3( size, -size,  size),
         Vector3( size,  size,  size),
         Vector3(-size,  size,  size),
         Vector3(-size, -size,  size)
     ]; 
     
     // make triangles
     var top_triangles = [
         5, 2, 1,
         5, 1, 6
     ];
     var back_triangles = [
         0, 1, 3,
         1, 2, 3
     ];
     var left_triangles = [
         0, 7, 6,
         0, 6, 1
     ];
     var front_triangles = [
         4, 5, 6,
         4, 6, 7
     ];
     var right_triangles = [
         3, 2, 5,
         3, 5, 4
     ];
     var bottom_triangles = [
         3, 4, 7,
         3, 7, 0
     ];
     
     // generate uvs
     var uv: Vector2[] = new Vector2[vertices.Length];
     for (var j = 0; j < uv.Length; j++) {
         uv[j] = Vector2(vertices[j].x * 0.5, vertices[j].z * 0.5);
     }
 
     // set materials (these are defined globally per chunk)
     var side_material = (CheckBlock(position + Vector3.up)) ? ground_side : ground_side_top;
     block.renderer.materials = [
          ground_top,
          side_material,
          side_material,
          side_material,
          side_material,
          ground_bottom
     ];
 
     // build new mesh
     var mesh = new Mesh();
     mesh.subMeshCount = 6;
     mesh.vertices = vertices;
     if (!CheckBlock(position + Vector3.up)) mesh.SetTriangles(top_triangles, 0);
     if (!CheckBlock(position + Vector3.back)) mesh.SetTriangles(back_triangles, 1);
     if (!CheckBlock(position + Vector3.left)) mesh.SetTriangles(left_triangles, 2);
     if (!CheckBlock(position + Vector3.forward)) mesh.SetTriangles(front_triangles, 3);
     if (!CheckBlock(position + Vector3.right)) mesh.SetTriangles(right_triangles, 4);
     if (!CheckBlock(position + Vector3.down)) mesh.SetTriangles(bottom_triangles, 5);
     mesh.uv = uv;
     mesh.RecalculateNormals();
     
     // set mesh
     meshFilter.mesh = mesh;
     
 }

The last question i have is about the materials. I think I did something wrong generating the UVs of the voxels, because the textures are rendered as a solid color. I've tried messing around with the UVs (again after reading up on them), the textures and the materials' tilings, which changed some stuff, but didn't make it render correctly. Does this make sense with the function above?

I would love to hear your input, cause i have no ideas left anymore. will continue browsing for answers in the meantime ;) thanks a bunch guys!!

Comment
Add comment · Show 1
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 Zarenityx · Jun 05, 2013 at 12:13 PM 0
Share

I thought I should say this, but as it is more of a suggestion than an answer at the moment, I thought it would be better to use a comment-

Your chunk sizes should really be powers of two. 10s and 5s are easy for humans to understand, but computers will be able to do calculations much faster with 16s and 32s. Besides, you dont really need to do many calculations by hand if you are program$$anonymous$$g a computer to do these calculations.

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by Zarenityx · Jun 05, 2013 at 12:09 PM

Hi. I am also working on a voxel engine, only mine is 3d, not 2.5. It is the same basic concept, though.

First off, about your draw calls/combining problem- you, like many others, have made the most common mistake in the world of voxels: you are trying to make the voxels physical objects. What you really want to do to make it fast is to use 'hypothetical voxels'. These are either classes or structs with sub-functions (which works a lot faster, if you know how to use them.) and have variables like type, solidity, and transparency (this allows for glass-like voxels and stuff.). These will extend System.Object, NOT monobehavior. Then, instead of adding them through instantiation to your chunks, you iterate through and set them to the desired voxel. (something like: voxels[x,y,z] = Voxel.Air(); ). All the voxel data is still there, but there is no time wasted in the instantiation of individual objects. This also means that there is no need for using CombineChildren, because there are no children to combine. Instead, a simple modification can be done to your triangle reduction code. Instead of creating all the possible verts first, then making the triangles that you need, try creating a vertexindex integer, a list (not an array) of verts, and a list of triangles. Then have a bunch of if statements:

if the voxel is solid
if the voxel on this side is transparent or null

add the needed verts to the verts list, then add the triangles to the tris list, then the uvs, etc. When adding the tris, however, do it based on the vertex index. always treat the vertex index as if it is zero (even though it is not, and if you set it to zero it won't work) and add select the vertices by adding the correct number to the vertex index.

(when for loops are done)- add the verts, tris, uvs, etc. to the mesh, and set the mesh to the chunk's mesh filter and collider.

That way, there is only one mesh per chunk, no child objects, and no instantiation (which is a fairly slow process.).

Next, your uvs problem- I am not sure what you are doing with all the materials and stuff, but here is how I did it: I added a few arrays in my hypotheticals, for the top,bottom, and sides. (although I am thinking about revising this, given that the memory usage of my game will be very high). Then I made a texture atlas and used it to make a single material, which is applied to every chunk individually and by default. Then I got the uv coords for my chunk mesh from the uv coords of the voxels. Also remember that UV coords are expressed in Vector2s comprised of decimals between 0 and 1, where 0,0 is the bottom left of the texture, and 1,1 is the top right. Essentially, uvs are the percentage of the images pixels from the bottom left expressed in decimal form.

I hope this helps.

Comment
Add comment · Show 1 · 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 thijsdaniels89 · Jun 05, 2013 at 01:09 PM 0
Share

Your answer is amazing, thank you so much!! This will definitely get me back on the right track! I will do lots of revising and if I find out something interesting a I'll post it here in case it's useful to someone else later. Thanks again for your help!!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

14 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

Related Questions

How to merge generated meshes 0 Answers

Combining meshes (different materials) together for rotation/translation 1 Answer

CombineMeshes() Not Working Properly? 0 Answers

Voxel Mesh has Lines Between the Voxels 1 Answer

What is wrong with this mesh editing code? 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