• 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 Joseph_Coder · Jul 10, 2021 at 03:00 AM · optimizationterrain generationvoxels

How to Optimize a Voxel-Based Procedural Terrain Generation

I'm building a game with a voxel-based infinite terrain generation, like Minecraft. I have already done the occlusion culling work, and it helped a lot, but my 16x64x16 chunks are still very slow/laggy when rendering a new terrain (I don't know why exactly), which is unplayable.

I thought about using multi-threading to render chunks, but Minecraft only uses one thread and it's very fast to generate terrain. I was looking for a way to optimize my game without "pushing the dust under the carpet".

Maybe the occlusion culling process is taking too long to be executed, or my chunks are too big, I can't find a good way to optimize it and make the game playable... Any Ideas?

This is how I'm creating meshes:

 Voxel[,,] voxels;
 
     List<Vector3> vertices = new List<Vector3>();
     List<int> triangles = new List<int>();
 
     private void SetupVoxels()
     {
         this.voxels = new Voxel[xSize + 2, ySize + 2, zSize + 2];
 
 
         for (int x = 0; x < xSize + 2; x++)
         {
             for (int y = 0; y < ySize + 1; y++)
             {
                 for (int z = 0; z < zSize + 2; z++)
                 {
                     Vector3 blockPos = new Vector3(x, y, z);
 
                     Voxel voxel = new Voxel(blockPos, chunkPos, 0, ySize);
 
                     voxels[x, y, z] = voxel;
 
                 } //z
             } //y
         } //x
 
     }
 
     private void Generate()
     {
         SetupVoxels();
         
         int tris = 0;
 
         //Go through each block
         for (int x = 1; x < xSize + 1; x++) 
         {
             for (int y = 0; y < ySize; y++)
             {
                 for (int z = 1; z < zSize + 1; z++)
                 {
 
                     if (voxels[x, y, z].GetVoxelType() != BlockType.Air)
                     {
                         Vector3 blockPos = new Vector3(x, y, z);
 
                         Voxel voxel = new Voxel(blockPos, chunkPos, tris, ySize);
 
                         if (voxels[x, y, z - 1].GetVoxelType() == BlockType.Air)
                         {
                             voxel.AddFace(BlockSide.Front);
                         }
 
                         if (voxels[x - 1, y, z].GetVoxelType() == BlockType.Air)
                         {
                             voxel.AddFace(BlockSide.Left);
                         }
 
                         if (voxels[x, y, z + 1].GetVoxelType() == BlockType.Air)
                         {
                             voxel.AddFace(BlockSide.Back);
                         }
 
                         if (voxels[x + 1, y, z].GetVoxelType() == BlockType.Air)
                         {
                             voxel.AddFace(BlockSide.Right);
                         }
 
                         if (voxels[x, y + 1, z].GetVoxelType() == BlockType.Air)
                         {
                             voxel.AddFace(BlockSide.Top);
                         }
 
                         if (y > 0)
                         {
                             if (voxels[x, y - 1, z].GetVoxelType() == BlockType.Air)
                             {
                                 voxel.AddFace(BlockSide.Bottom);
                             }
                         }
 
                         triangles.AddRange(voxel.Triangles);
                         vertices.AddRange(voxel.Vertices);
 
                         voxels[x, y, z] = voxel;
                         tris += 8;
                     }
 
 
                 }
             }
         }
 
     }
Comment
Add comment · Show 12
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 Llama_w_2Ls · Jul 10, 2021 at 03:29 PM 0
Share

Firstly, how are you rendering your world in the first place? What's the code for creating chunks. Are you instantiating thousands of cubes, or creating the mesh data yourself.

avatar image Joseph_Coder Llama_w_2Ls · Jul 10, 2021 at 05:29 PM 1
Share

Each chunk has its own single mesh, to make a chunk mesh I go through some for loops and check whether or not the block should show a face. I don't instantiate a block to get its vertices and triangles.

avatar image Llama_w_2Ls Joseph_Coder · Jul 11, 2021 at 10:47 AM 0
Share

I'm not entirely sure what the reason is for the slow chunk generation. There could be many culprits, such as using lists instead of a dictionary, for faster lookup times, (an example, not saying this is the main cause).


To find the culprit, use the System.Diagnostics namespace and use the Stopwatch class to time each section of your method. Like so:

         void MethodThatTakesALongTime()
         {
             Stopwatch watch = new Stopwatch();
             watch.Start();
 
             // Execute method part 1
 
             UnityEngine.Debug.Log(watch.ElapsedMilliseconds);
             watch.Reset();
 
             // Execute method part 2
 
             UnityEngine.Debug.Log(watch.ElapsedMilliseconds);
 
             watch.Stop();
         }

Once, you know what method/s are taking the longest, can you post only those sections please? Thanks.

Show more comments
avatar image datnasty2_0 · Jul 12, 2021 at 08:32 PM 0
Share

I would like to know how to fix this also.

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by KidsWithSpraycans · May 19 at 12:40 PM

Although this post is specific to voxel terrain, anyone looking into making a voxel game should try to optimize their 3D voxel models, since they can be quite inefficient.


I've created the Ultimate Voxel Optimizer as a way of helping this problem. Using classic meshing techniques with voxel models doesn't result in the most optimal models. UVO, however, uses a custom meshing algorithm to ensure that you get the best reduction out of all model optimizer programs.

Simply load in your .vox models from MagicaVoxel, select your export method and format, and click export. Some models can receive a 50% reduction in polygon count, with more features coming soon! The program is currently $3.99, and available on Windows, Mac, and Linux!


You can get more info at https://nateonus.itch.io/ultimate-voxel-optimizer

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 DBLakmaaker · May 21 at 02:52 AM 0
Share

And what use is that for generating terrain at runtime?

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.

Follow this Question

Answers Answers and Comments

129 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 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 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How do you handle water in voxel games? 0 Answers

Profiler shows Object.ElementAddr_3_8() called over a million times. What is it? How do I reduce this? 1 Answer

How to mix different amplitudes and frequencies when procedurally generating terrain? (Perlin Noise) 0 Answers

Voxel Marching Hibrid 0 Answers

Do large numbers of stopped particle systems hurt performance? 1 Answer


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