# Godus like procedural terrain generation

Discussion in 'Works In Progress - Archive' started by ExSoax, Mar 31, 2016.

1. ### ExSoax

Joined:
Nov 27, 2014
Posts:
11
Hi guys,
I'm making a video game inspired by Godus mobile game. I did a terrain generator and it works fine but it is really slow. Can someone help me for optimizing my code?

This is how it looks:

The algorithm is based on the generation of layered deformed circumferences, starting from top ( small range shapes ) to bottom ( high range shapes ). This is the function that i would like to optimize:

Code (CSharp):
1.
2.
3. delegate float SinusoidalTerm(float x);
4.
5. public static void DrawBlob(int MaxX, int MaxY, int CenterX, int CenterY, int OriginalRadius, float Height, ref float[,] Heights, ref float[,,] AlphaMap)
6.     {
7.         int TermCount = Random.Range(1,5);
8.
9.         float[] TermOffsets = Enumerable.Range(0, TermCount)
10.                               .Select(r => Random.Range(0f, 2 * Mathf.PI))
11.                               .ToArray();
12.
13.         float[] TermWeights = Enumerable.Range(0, TermCount)
14.                         .Select(r => Random.Range(0f, 1f))
15.                         .ToArray();
16.
17.         SinusoidalTerm Term = (x) =>
18.         {
19.             float Sum = 0;
20.             for (int i = 0; i < TermCount; i++)
21.                 Sum += TermWeights[i] * Mathf.Sin(TermOffsets[i] + 2 * Mathf.PI * x);
22.             return Sum;
23.         };
24.
27.
30.             {
31.                 double Eq1 = ox * ox + oy * oy;
33.                 if (
34.                    Eq1 <= Eq2
35.                 )
36.                 {
37.                     int x = CenterX + (int)ox, y = CenterY + (int)oy;
38.                     if (x < MaxX && x > 0 && y < MaxY && y > 0 && Height > Heights[x, y])
39.                     {
40.                         Heights[x, y] = Height;
41.                         try
42.                         {
43.                             AlphaMap[x, y, 0] = 1f - 10 * Height;
44.                             AlphaMap[x, y, 1] = Mathf.Abs(Height - 0.5f);
45.                             AlphaMap[x, y, 2] = Height * 2;
46.                         }
47.                         catch { }
48.                     }
49.                 }
50.             }
51.     }
52.

2. ### mgear

Joined:
Aug 3, 2010
Posts:
9,072
Do yo need that try-catch there?

Did you check with Profiler if any other part is slowing down? (like, for example applying the heightmap to terrain is quite slow)

3. ### ExSoax

Joined:
Nov 27, 2014
Posts:
11
Do u think that the try catch block can slow a bit? I will check with the profiler thanks.

Joined:
Aug 3, 2010
Posts:
9,072
5. ### ExSoax

Joined:
Nov 27, 2014
Posts:
11
I did some tries... well, removing in the:
Code (CSharp):
this term:
Code (CSharp):
will speed incredibly up the generation.
With that term it tooks something like 59 seconds while without it tooks 5 seconds... That code is usefull for deforming the circles... Without that it looks like this:

6. ### mgear

Joined:
Aug 3, 2010
Posts:
9,072
other things i've heard:
- Mathf. is slower then System.Math
- Using LINQ is slower
- Use bit-shifting in calculations where possible
- Random.range() is bit slow
- Sine/Cosines are bit slow (if you are doing lots of them)

there's also other tips listed here (see comments)
http://unitycoder.com/blog/2014/04/23/unity-optimization-tips/

7. ### NightAvail

Joined:
Feb 23, 2015
Posts:
13
I also had some issues with slow terrain loading as the content for my game is dynamic and loads maps based on colormaps, splatmaps, normalmaps, etc. Initially my load time was 2 min and 32 sec to load up everything, not ideal... However after some playing around I got the load time down to just 4 sec (no caching) which is a huge difference when loading a ton of data.

I'd suggest making clever use of arrays. Don't rely on Texture.GetPixel32 and instead save the pixels into a Color32[x,y] array if you need access to it.

List<> was a huge factor in my slow processing. A simple assignment would cost me 5 seconds... Don't get me wrong, initializing List<> objects are fast, but when it came to modifying them I experienced some issues; and so I created a new type of List<> object which acts more like a Dictionary now than a list, and is super fast on lookups.

Replace every string concatenation you may have with a StringBuilder and make use of string.Format(). Watch your memory usage however. I ended up creating something I call a ByteReader which is more memory-efficient due to the fact that I'm loading in a ton of custom scripts that can contain Unicode characters. However StringBuilder is great and will satisfy most conditions.

Utilize logging of some sort. I created my own custom profiler and I'm constantly saving as much as possible into log files to identify places I can improve.

Identify places where you can use multi-threading (especially with logging). This is another reason to move the Texture.GetPixel32 data into its own array so you can use it in separate thread later on. Unity's rendering-based classes are not available for use in separate threads, however structures like Vector, Color32, etc are available for use. I believe this was said before but definitely use Color32 over Color.

Speaking of Color32, I noticed a slight increase in performance when I created my own IsEqual method and checked the bytes myself...

Finally, after everything is processed use a database like SQLite to cache your results. After caching my results my terrain processes in around 2 sec. I also compress some of my results (textures that I created dynamically) into blobs.

I hope that helps and good luck!