Search Unity

Generating sc2000 terrain, performance

Discussion in 'Scripting' started by Ahnuld, Jul 6, 2014.

  1. Ahnuld

    Ahnuld

    Joined:
    Oct 20, 2012
    Posts:
    15
    Hi All,

    I'm trying to generate a terrain like in the old game Simcity 2000, I've written the following code:
    http://pastebin.com/rLSW7zXn and it generates something like this:


    Now I can't increase the size of the terrain much further than 32x32 tiles, because it uses 12 vertices per grid square, it hits the unity limit of 65.000 vertices pretty quickly. Also it takes long to generate the terrain mesh, but that is probably caused by my sucking algorithmic skills.

    If at all possible, I'd like to generate terrains of at least 128x128 of 256x256 tiles, but this approach is clearly not working. What approach or further reading would you recommend?
     
    GarthSmith likes this.
  2. SanderAKALego

    SanderAKALego

    Joined:
    Jul 17, 2010
    Posts:
    32
    When I wrote my own terrain generator I simply divided the map into smaller chunks
    So in your case if you generate 32x32 chunks you'd have to generate 16 cunks for 128x128 or 64 chunks for 256x256

    Here's some pseudocode
    Code (CSharp):
    1. public class TerrainGeneration
    2. {
    3.     public int MapSizeX = 256;
    4.     public int MapSizeY = 256;
    5.  
    6.     public int maxChunkSize = 32;
    7.  
    8.     private Transform root;
    9.  
    10.     void GenerateTerrain()
    11.     {
    12.         root = new GameObject("Root").transform;
    13.  
    14.         int chunksX = MapSizeX / maxChunkSize;
    15.         int chunksY = MapSizeY / maxChunkSize;
    16.  
    17.         for (int x = 0; x < chunksX; x++)
    18.         {
    19.             for (int y = 0; y < chunksY; y++)
    20.             {
    21.                 GameObject chunk = GenerateChunk(x,y);
    22.                 chunk.transform.parent = root;
    23.             }
    24.         }
    25.     }
    26.  
    27.     GameObject GenerateChunk(int x_Offset, int y_Offset){
    28.         //Remember to offset the object with x_offset * maxchunksize
    29.         //and y_offset * maxchunksize
    30.     }
    31. }
     
  3. Ahnuld

    Ahnuld

    Joined:
    Oct 20, 2012
    Posts:
    15
    Thanks :) this approach would work, but I'm having difficulty implementing it with the current algorithm (I think that is the actual problem, it's also way to slow). I'll keep trying.
     
  4. SanderAKALego

    SanderAKALego

    Joined:
    Jul 17, 2010
    Posts:
    32
    No problem and good luck!
     
  5. Ahnuld

    Ahnuld

    Joined:
    Oct 20, 2012
    Posts:
    15
    Thanks!

    I implemented your solution and I can now generate a 256x256 terrain in mere seconds.
    It looks like this:


    Where the chunks meet, it's still buggy and I'm not sure how to fix this, but it must be possible. If anyone wants the code it's here: http://pastebin.com/EkiVw9LS
     
  6. Ahnuld

    Ahnuld

    Joined:
    Oct 20, 2012
    Posts:
    15
    I'm stuck on this. The problem is that when tiles are generated, the position of the vertices in the corners are determined by the previous tile on the X axis and the previous tile on the Y axis. This is needed to create the sloping.

    When a new chunk is generated, those vertices are not available for the first rows of tiles on the X and Y axes, and calculation of the vertex positions is no longer possible, hence there are gaps. If anyone wants the code, it's here: http://pastebin.com/FC3kzJpn
     
  7. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    938
    I could try to help you out. But first I'd like to know, do you want to generate the whole terrain up-front or is it supposed to generate on the fly (like, when the camera moves, new terrain gets generated) ?
     
  8. Ahnuld

    Ahnuld

    Joined:
    Oct 20, 2012
    Posts:
    15
    Hi wasstraat, any help, even just a hint of what I'd have to do, would be very welcome.
    I'd like the terrain to be generated up front, based on the 2D array in the variable named 'grid'. At the moment there's just generated perlin noise in it (should probably replace that with something more landscape-like or just load in height maps).

    The only dynamic thing I can think of, is that it would be cool to be able to edit the terrain afterwards. I'm not sure how to do this yet, maybe edit the 2D array and recalculate vertices of the affected chunk of terrain, or edit the vertices directly in some way.

    Edit: being able to have more or less infinite terrain by dynamically loading and displaying chunks would of course be super awesome, I just haven't thought about it that much yet because I guessed it would be very difficult to implement. I wanted to keep it simple as this is my first try with this kind of thing.
     
    Last edited: Jul 6, 2014
  9. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    938
    generating things up front makes things a bit easier already. I'm assuming that the values in the 'grid' are representing point on the corners of the squares? If not, I would advise to do so.
    For mesh simplification, you have to make a few observations here:
    - currently for each square, you are generating 4 triangles with seperate vertices
    - Vertices with the same position could be merged if your texturing allows you to do so. (UV's)
    - Considering every combination of grid offsets on the corners (-1 below level, 0 the same level, +1 above level), every square can represent their surface with only 2 triangles (take a pen and some paper and draw every possible scenario out, I may have missed some cases in my head but this is what I could think of)
    - You can get rid of the center vertex if you take ambiguity into account

    The editing is really simple. You just have to make sure you store your grid somewhere. Then when for example a player click somewhere, figure out where that position is in the grid (its index), modify it's value and regenerate the mesh from scratch. Modifying the mesh directly is a bit ugly and is error-prone (with neighbouring tiles etc.)

    I can imagine that what Im saying here is a bit hard to understand, if you need to I can draw up some images for you
     
  10. NeverConvex

    NeverConvex

    Joined:
    Jun 26, 2013
    Posts:
    88
    I've run into a similar issue in working with a voxel terrain generator; what appears to me to be the ideal solution is to have your landscape's value be determined by world position, rather than by its local coordinates inside of each chunk. To set the height value at a particular unit within a chunk, then, you need to first convert the unit within the chunk to its corresponding world coordinates, and assign it the appropriate value for that world coordinates vector.

    Depending on how you handle the conversion of chunk-units to world coordinates, this may require overlapping chunks to work. It enforces consistency among neighboring chunks by determining their heightmap (or some other generalized terrain function) value according to a common metric (worldspace), rather than determining heightmap values in a chunk-specific way.
     
  11. Ahnuld

    Ahnuld

    Joined:
    Oct 20, 2012
    Posts:
    15
    Thank you so much! I can't believe how stupid it was not to do this. Everything works great now and the code is a lot cleaner.

    Very true. This is next on my to-do list.

    I'd prefer this way too, also makes it easier to make the terrain persistent etc. Thanks for pointing me in the right direction here :)

    Your explanations are very clear! You've helped me immensely!
     
  12. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    938
    Good to hear that it helped you :)

    If you have any further questions, feel free to ask them or send me a private message
     
  13. Deleted User

    Deleted User

    Guest

    Hey i was looking this and i wonder if somebody could post the code of making this kind of terrain?? Becouse i think i get a little bit late in time