Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Terrain generation question

Discussion in 'Scripting' started by MrMinecraft97, Jan 10, 2021.

  1. MrMinecraft97

    MrMinecraft97

    Joined:
    Jun 29, 2019
    Posts:
    2
    I have looked through my code multiple time and can not figure why the terrain objects do not line up with each other. I have a terrain object with the "SingleChunkGen" script on it, which has a empty object as its parent, with the "ChunkInfo" on it. I then have a separate empty object with the "TerrainGen" script attached, and a prefab of the first empty object set as the "ChunkPrefab" GameObject in the inspector. Also if anyone knows how to fix the cliffs at the edge of each terrain that would be nice. I have also attached an image of the heirarchy, and inspector of each object. edited.png
    TerrainGen script:
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class TerrainGen : MonoBehaviour
    5. {
    6.  
    7.     public static Vector2[] chunkXYorder = new Vector2[1];
    8.     public int maxItterations = 20;
    9.     public int chunkSize = 512;
    10.     public GameObject chunkPrefab;
    11.  
    12.     void Start()
    13.     {
    14.  
    15.         for (int x = 0; x <= 5; x++)
    16.         {
    17.             for (int y = 0; y <= 5; y++)
    18.             {
    19.                 loadChunk(x, y);
    20.             }
    21.         }
    22.     }
    23.  
    24.     void loadChunk(int x, int y)
    25.     {
    26.         if (checkChunkExistance(x, y))
    27.         {
    28.             Debug.Log("Chunk at " + x + " " + y + " exitsts, loading");
    29.             //load from saved state - not implemented yet
    30.         }
    31.         else
    32.         {
    33.             Debug.Log("Chunk at " + x + " " + y + " does not exitst, genrating new");
    34.             generateChunk(x, y);
    35.         }
    36.     }
    37.  
    38.     void unloadChunk(int x, int y)
    39.     {
    40.         //save chunk - not implemented yet
    41.     }
    42.  
    43.     void generateChunk(int x, int y)
    44.     {
    45.         GameObject currentChunk = Instantiate(chunkPrefab, new Vector3(x * chunkSize, 0, y * chunkSize), Quaternion.identity);
    46.         currentChunk.GetComponent<ChunkData>().chunkX = x;
    47.         currentChunk.GetComponent<ChunkData>().chunkY = y;
    48.         currentChunk.transform.GetChild(0).gameObject.GetComponent<SingleChunkGen>().GenerateTerrain(x, y, chunkSize);
    49.     }
    50.  
    51.     bool checkChunkExistance(int x, int y)
    52.     {
    53.         bool found = false;
    54.         int itteration = 0;
    55.         int currentSearchPoint = chunkXYorder.Length;
    56.         int xCorrect = 0;
    57.         while (!found)
    58.         {
    59.             if (currentSearchPoint > chunkXYorder.Length - 2 || currentSearchPoint < 0 || itteration > maxItterations)
    60.             {
    61.                 return false;
    62.             }
    63.  
    64.             itteration++;
    65.             if (chunkXYorder[currentSearchPoint].x == x)
    66.             {
    67.                 xCorrect = currentSearchPoint;
    68.                 found = true;
    69.                 break;
    70.             }
    71.             else if (chunkXYorder[currentSearchPoint].x > x)
    72.             {
    73.                 currentSearchPoint -= chunkXYorder.Length / itteration;
    74.                 continue;
    75.             }
    76.             else if (chunkXYorder[currentSearchPoint].x < x)
    77.             {
    78.                 currentSearchPoint += chunkXYorder.Length / itteration;
    79.                 continue;
    80.             }
    81.         }
    82.         itteration = 0;
    83.         while (chunkXYorder[currentSearchPoint].x == x)
    84.         {
    85.             currentSearchPoint++;
    86.             if (currentSearchPoint > chunkXYorder.Length - 2 || itteration > maxItterations)
    87.             {
    88.                 break;
    89.             }
    90.             if (chunkXYorder[currentSearchPoint].y == y)
    91.             {
    92.                 return true;
    93.             }
    94.         }
    95.         currentSearchPoint = xCorrect;
    96.         while (chunkXYorder[currentSearchPoint].x == x)
    97.         {
    98.             currentSearchPoint--;
    99.             if (currentSearchPoint < 0 || itteration > maxItterations)
    100.             {
    101.                 return false;
    102.             }
    103.             if (chunkXYorder[currentSearchPoint].y == y)
    104.             {
    105.                 return true;
    106.             }
    107.         }
    108.         return false;
    109.     }
    110. }
    111.  
    SingleChunkGen Script:
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class SingleChunkGen : MonoBehaviour
    5. {
    6.     public int height = 20;
    7.     public float scale = 20;
    8.  
    9.     public void GenerateTerrain(int chunkX, int chunkY, int chunkSize)
    10.     {
    11.         Terrain terrain = GetComponent<Terrain>();
    12.         TerrainData terrainData = new TerrainData();
    13.         terrainData.heightmapResolution = chunkSize;
    14.         terrainData.size = new Vector3(chunkSize, height, chunkSize);
    15.         terrainData.SetHeights(0, 0, GenerateHeights(chunkX, chunkY, chunkSize));
    16.         terrain.terrainData = terrainData;
    17.         GetComponent<TerrainCollider>().terrainData = terrainData;
    18.     }
    19.  
    20.     float[,] GenerateHeights(int chunkX, int chunkY, int chunkSize) {
    21.         float[,] heights = new float[chunkSize, chunkSize];
    22.  
    23.         for (int i = 0; i < chunkSize; i++)
    24.         {
    25.             for (int e = 0; e < chunkSize; e++)
    26.             {
    27.                 heights[i, e] = CalculateHeight(i + chunkSize * chunkX, e + chunkSize * chunkY, chunkSize);
    28.             }
    29.         }
    30.         return heights;
    31.     }
    32.  
    33.     float CalculateHeight(int x, int y, int chunkSize)
    34.     {
    35.         float xCord = (float)x / chunkSize * scale;
    36.         float yCord = (float)y / chunkSize * scale;
    37.  
    38.         return Mathf.PerlinNoise(xCord, yCord);
    39.     }
    40. }
    41.  
    ChunkData Script:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class ChunkData : MonoBehaviour
    4. {
    5.     public int chunkX;
    6.     public int chunkY;
    7. }
    8.  
     

    Attached Files:

  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,517
    First before you involve terrain, use use math on your chunk generator and ensure this is true:

    - The height value for the lower right corner of a square matches precisely the height value of the upper left corner of the adjacent square.

    Or more explicitly, make sure the inputs to Mathf.Perlin at the ultimate corner of a square match the inputs to the adjacent square.

    You can verify all of that numerically, without involving the terrain. Only once you're sure of your chunk offset math should you start pushing it to the terrain height.
     
  3. MrMinecraft97

    MrMinecraft97

    Joined:
    Jun 29, 2019
    Posts:
    2
    As far a I can tell, they should be the correct offsets.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,517
    Print them with Debug.Log, prove the source data is good. If they're not correct, nothing else will matter.
     
  5. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    687
    Heightmaps are 1 larger in each dimension than the terrain size, which is reflected by your "chunkSize". They are arrays of the vertices so there's one extra. (You set heights of vertices, not faces.) Try setting those to 513 and see if that works, seems like it might, given that your issue is at the edges.