Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 /
avatar image
0
Question by Epicshark · Sep 24, 2014 at 03:28 PM · optimizationprocedural meshprocedural generationprocedural-terrain

How can I generate procedural 3D geometry faster?

In my game I have 3D grids that are generated then the y positions of the vertices are displaced to perlin noise, which makes terrain which has to be loaded in chunks. Currently I have the grid loading in chunks, the player can go in every direction infinitely and the way I do this is by removing the 3 chunks behind you and instantiating 3 chunks in front of you. This would be ok, if it didn't take ten seconds to make the 3 chunks in front of you. How can I generate the chunks faster? I have experimented with not using perlin noise, which I thought was what was making it slow, but it didn't make a difference. Here's my code for generating the chunk, which are instantiated in another script. (well, its not really my code)

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class MeshTerrain : MonoBehaviour {
 
     public int sizeOfChunk = 128;
     private int size;
     private int length;
     public float spacing = 1;
     public MeshFilter terrainMesh = null;
 
     public int eMid = 2;
     public int sMid = 5;
     public int eHigh = 5;
     public int sHigh = 10;
     public int eLow = 1;
     public int sLow = 5;
     public int eMacro = 2;
 
     public int eTemp = 10;
     public int sTemp = 2;
     static int tempRandomiser = Random.Range (0,10000);
 
     public int ePrecip = 10;
     public int sPrecip = 2;
     static int precipRandomiser = Random.Range (0,10000);
 
     static int randomiser = Random.Range(0,10000);
 
     // Use this for initialization
     void Start () {
         size = sizeOfChunk + 3;
 
         if (terrainMesh == null)
         {
             Debug.LogError("ProceduralTerrain requires its target terrainMesh to be assigned.");
         }
         GenerateMesh();
     }
     
     // Update is called once per frame
     void Update () {
     
     }
 
     //this part generate terrain
     float GetHeight (float x, float z){
         float height;
         float heightA = Noise.Noise.GetNoise((x+transform.position.x) / sMid + randomiser,0, (z+transform.position.z) / sMid + randomiser) * -eMid;
         float heightB = Noise.Noise.GetNoise((x+transform.position.x) / sHigh + randomiser,0, (z+transform.position.z) / sHigh + randomiser) * -eHigh;
         float heightC = Noise.Noise.GetNoise((x+transform.position.x) / sLow + randomiser,0, (z+transform.position.z) / sLow + randomiser) * -eLow;
 
         float heightM = Noise.Noise.GetNoise((x+transform.position.x)  + randomiser,0, (z+transform.position.z)  + randomiser) * -eMacro +800;
 
         //float temperature = Noise.Noise.GetNoise((x+transform.position.x)/1.2f+ tempRandomiser,0, (z+ transform.position.z)/1.2f + tempRandomiser) * eTemp;
         //float precipitation = Noise.Noise.GetNoise((x+transform.position.x)/1.2f+ precipRandomiser,0, (z+ transform.position.z)/1.2f + precipRandomiser) * ePrecip;
         height = heightA + heightB + heightC + heightM;
         //Debug.Log (precipitation);
         //if(precipitation >= 10 && temperature <= 10){
         //    height -= 10;
         //}
         return height;
     }
 
     void GenerateMesh ()
     {
         List<Vector3[]> verts = new List<Vector3[]>();
         List<int> tris = new List<int>();
         List<Vector2> uvs = new List<Vector2>();
 
         for (int z = 0; z < size; z++)
         {
             verts.Add(new Vector3[size+1]);
             for (int x = 0; x < size; x++)
             {
                 Vector3 current_point = new Vector3();
                 current_point.x = (x * spacing);
                 current_point.z = z * spacing;
                 
                 current_point.y = GetHeight(current_point.x-1, current_point.z);
                 
                 verts[z][x] = current_point;
                 //uvs.Add(new Vector2(x,z)); 
                 if (x-1 <= 0 || z <= 0 || x >= size)
                 {
                     continue;
                 }
                 // Generate the triangle north of you.
                 tris.Add(x + z*size);
                 tris.Add(x + (z-1)*size);
                 tris.Add((x-1) + (z-1)*size);
                 tris.Add((x-1) + z*size);
                 tris.Add(x + z*size);
                 tris.Add((x-1) + (z-1)*size);
             }
             
             // Unfold the 2d array of verticies into a 1d array.
             Vector3[] unfolded_verts = new Vector3[size*size];
             int i = 0;
             foreach (Vector3[] v in verts)
             {
                 v.CopyTo(unfolded_verts, i * size);
                 i++;
             }
             
             // Generate the mesh object.
             Mesh ret = new Mesh();
             ret.vertices = unfolded_verts;
             ret.triangles = tris.ToArray();
             //ret.uv = uvs.ToArray();
             
             // Assign the mesh object and update it.
             ret.RecalculateBounds();
             ret.RecalculateNormals();
             terrainMesh.mesh = ret;
 
         }
     }
 
 }
 


So, how can I make this faster? Is there something here which is slowing down the game or do I need to try a different method?

Comment
Add comment · Show 2
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 robertbu · Sep 24, 2014 at 04:00 PM 0
Share

I see inefficiency here, but I'm not sure it is enough to account for the kind of slowness you describe. I'm assu$$anonymous$$g a chunk is one mesh. I just ran a quick test of some chunk code I have. It took aprox. eight seconds to generate 1000 meshes, each containing 64$$anonymous$$ of vertices.

The thing that jumps out at me is the use of generic Lists. You end up with a function call per entry, plus the resizing and copying that goes on underneath as the list has to grow.

avatar image Cherno · Sep 24, 2014 at 05:03 PM 0
Share

First: check out this thread if you haven't already:

http://forum.unity3d.com/threads/after-playing-$$anonymous$$ecraft.63149/

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by CalxDesign · Sep 24, 2014 at 04:30 PM

Have you established what's actually being done in that 10 seconds? Could you not do this constantly so you're streaming a single line of verts/tri's rather than doing entire blocks of terrain at once. The overhead might be considerably less.

Comment
Add comment · 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
0

Answer by levis501 · Sep 24, 2014 at 10:15 PM

Give the built-in profiler a try to speed up your code. http://docs.unity3d.com/Manual/ProfilerWindow.html

For example, use Profiler.BeginSample and Profiler.EndSample to mark sections of your code and see how much time is being spent in each section.

 void Update() {
   for (int i=0; i<count; i++) {
      Profiler.BeginSample("Section 1");
      SomeFunction();
      Profiler.EndSample();
      Profiler.BeginSample("Section 2");
      AnotherFunction();
      Profiler.EndSample();
   }
 }

The profiler will tell you about the time used in the different sections. Start with the section that takes the longest time and try to optimize that first.

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 levis501 · Sep 24, 2014 at 11:06 PM 0
Share

I realize the profiler may not be available in the non-pro version. In that case, I would alternately comment out one section at a time, seeing which version runs faster.

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

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

How to create voxel-based procedural terrain 1 Answer

How do i Offset a Shader Graph material? 0 Answers

For loop not starting from zero 0 Answers

What is the best way to generate water bodies in a procedurally generated world? 1 Answer

Procedural Terrain Merge 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