Search Unity

Bug Groundlayer (Grass) not stacking as it should..

Discussion in 'Scripting' started by RealDerpCore, Aug 22, 2021.

  1. RealDerpCore

    RealDerpCore

    Joined:
    Jan 14, 2020
    Posts:
    13
    So I found out about this bug when my terrain generates and the perlin noise goes above my set height
    it doesnt let me place any more Tiles. Which is weird since I am telling it to place tiles above the perlin noise. Now I know I am making first a random noise, and than smoothing that out. So my theory is, that it doesnt let me place anything above the set height since there aren't any 1 : 2 there.

    1 meaning: stone
    2 meaning: cave


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Tilemaps;
    5. using UnityEngine.Sprites;
    6.  
    7. public class ProceduralGeneration : MonoBehaviour
    8. {
    9.  
    10.     [Header("Sprites")]
    11.     public Sprite treeSprite;
    12.  
    13.     [Header("Terrain Gen")]
    14.     [SerializeField] int width, height;
    15.     [SerializeField] float smoothness;
    16.     [SerializeField] int dirtLayerHeight = 5;
    17.     [SerializeField] int stoneLayerHeight = 3;
    18.  
    19.  
    20.     [Header("Caves")]
    21.     [Range(0, 100)]
    22.     [SerializeReference] int randomFillPercent;
    23.     [Range(0, 10)]
    24.     [SerializeField] int smoothAmount;
    25.  
    26.     int[] perlinHeightList;
    27.  
    28.     [SerializeField] TileBase stoneTile, caveTile, groundTile;
    29.     [SerializeField] Tilemap stoneTilemap, caveTileMap, groundTilemap;
    30.  
    31.     [SerializeField] float seed;
    32.  
    33.     [SerializeField] public int treeChance = 18;
    34.  
    35.  
    36.  
    37.     int[,] map;
    38.  
    39.     private void Start()
    40.     {
    41.         perlinHeightList = new int[width];
    42.         Generation();
    43.     }
    44.  
    45.     void Generation()
    46.     {
    47.         seed = Random.Range(10000, -10000);
    48.         stoneTilemap.ClearAllTiles();
    49.         map = GenerateArray(width, height, true);
    50.         map = TerrainGeneration(map);
    51.         SmoothMap(smoothAmount);
    52.         RenderMap(map, stoneTilemap, caveTileMap, groundTilemap, stoneTile, caveTile, groundTile);
    53.     }
    54.  
    55.     public int[,] GenerateArray(int width, int height, bool empty)
    56.     {
    57.         int[,] map = new int[width, height];
    58.         for(int x = 0; x < width; x++)
    59.         {
    60.             for(int y = 0; y < height; y++)
    61.             {
    62.                 map[x, y] = empty ? 0 : 1;
    63.             }
    64.         }
    65.         return map;
    66.     }
    67.  
    68.     bool IsInMapRange(int x, int y)
    69.     {
    70.         return x >= 0 && x < width && y >= 0 && y < height;
    71.     }
    72.  
    73.     public int[,] TerrainGeneration(int[,] map)
    74.     {
    75.         System.Random pesudoRandom = new System.Random(seed.GetHashCode());
    76.         int perlinHeight;
    77.         for (int x = 0; x < width; x++)
    78.         {
    79.             perlinHeight = Mathf.RoundToInt(Mathf.PerlinNoise(x / smoothness, seed) * height / 2);
    80.             perlinHeight += height / 2;
    81.             perlinHeightList[x] = perlinHeight;
    82.  
    83.             for (int y = 0; y < perlinHeight; y++)
    84.             {
    85.                 map[x, y] = (pesudoRandom.Next (1,100) < randomFillPercent) ? 1 : 2;
    86.             }
    87.         }
    88.         return map;
    89.     }
    90.  
    91.     void SmoothMap(int smoothAmount)
    92.     {
    93.         for (int i = 0; i < smoothAmount; i++)
    94.         {
    95.             for (int x = 0; x < width; x++)
    96.             {
    97.                 for (int y = 0; y < perlinHeightList[x]; y++)
    98.                 {
    99.                         if (x == 0 || y == 0 || x == width - 1 || y == perlinHeightList[x] - 1)
    100.                         {
    101.                             map[x, y] = 1;
    102.                         }
    103.                     else
    104.                     {
    105.                         int surroundingGroundCount = GetSurroundingGroundCount(x, y);
    106.                         if (surroundingGroundCount > 4)
    107.                         {
    108.                             map[x, y] = 1;
    109.                         }
    110.                         else if (surroundingGroundCount < 4)
    111.                         {
    112.                             map[x, y] = 2;
    113.                         }
    114.                     }
    115.                 }
    116.             }
    117.         }
    118.     }
    119.  
    120.     int GetSurroundingGroundCount(int gridX, int gridY)
    121.     {
    122.         int groundCount = 0;
    123.         for (int nebX = gridX - 1; nebX <= gridX+1; nebX++ )
    124.         {
    125.             for (int nebY = gridY - 1; nebY <= gridY+ 1; nebY++)
    126.             {
    127.                 if (IsInMapRange(nebX, nebY))
    128.                 {
    129.                     if (nebX != gridX || nebY != gridY)
    130.                     {
    131.                         if (map[nebX,nebY] == 1)
    132.                         {
    133.                             groundCount++;
    134.                         }
    135.                     }
    136.                 }
    137.             }
    138.         }
    139.         return groundCount;
    140.     }
    141.  
    142.     public void PlaceTile(Sprite tileSprite, float x, float y)
    143.     {
    144.         GameObject newTile = new GameObject();
    145.         newTile.AddComponent<SpriteRenderer>();
    146.         newTile.GetComponent<SpriteRenderer>().sprite = tileSprite;
    147.         newTile.name = tileSprite.name;
    148.         newTile.transform.position = new Vector2(x + 0.5f, y + 0.5f);
    149.     }
    150.  
    151.     public void RenderMap(int[,] map, Tilemap stoneTilemap, Tilemap caveTileMap, Tilemap groundTilemap, TileBase stoneTilebase, TileBase caveTilebase, TileBase groundTilebase)
    152.     {
    153.         int perlinHeight;
    154.  
    155.         for (int x = 0; x < width; x++)
    156.         {
    157.             perlinHeight = Mathf.RoundToInt(Mathf.PerlinNoise(x / smoothness, seed) * height / 2);
    158.             perlinHeight += height / 2;
    159.             perlinHeightList[x] = perlinHeight;
    160.  
    161.             for (int y = 0; y < height; y++)
    162.             {
    163.                 if (map[x, y] == 1 || y > perlinHeight - 1 && y < perlinHeight + stoneLayerHeight) //Stone Layer + Cave System
    164.                 {
    165.                     stoneTilemap.SetTile(new Vector3Int(x, y, 0), stoneTilebase);
    166.                 }
    167.                 else if (map[x, y] == 2 || y > perlinHeight -1 && y < perlinHeight) //Cave Background Layer
    168.                 {
    169.                     caveTileMap.SetTile(new Vector3Int(x, y, 0), caveTilebase);
    170.                 }
    171.                 if (y > stoneLayerHeight + perlinHeight - 1 && y < stoneLayerHeight + perlinHeight + dirtLayerHeight) //Top Layer (Grass)
    172.                 {
    173.                     groundTilemap.SetTile(new Vector3Int(x, y, 0), groundTilebase);
    174.                 }
    175.                 int tC = Random.Range(0, treeChance); //Generate Tree
    176.                 if (tC == 1 && y == perlinHeight + stoneLayerHeight + dirtLayerHeight)
    177.                 {
    178.                     PlaceTile(treeSprite, x, y);
    179.                 }
    180.             }
    181.         }
    182.     }
    183.  
    184.     void clearMap()
    185.     {
    186.         stoneTilemap.ClearAllTiles();
    187.         caveTileMap.ClearAllTiles();
    188.     }
    189. }
    190.  

    For example, look at the right top corner, the dirt should stack 5times like all of the others, but it only stacks 2 times..

    upload_2021-8-22_20-41-46.png
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,689
    What's that white bounds like with the blue corner dot? Isn't that the limit of the groundTileMap object? If you make it larger does that fix your problem?
     
  3. RealDerpCore

    RealDerpCore

    Joined:
    Jan 14, 2020
    Posts:
    13
    Yes so I tried that, in the debug window, but that either doesnt work :(
     
  4. RealDerpCore

    RealDerpCore

    Joined:
    Jan 14, 2020
    Posts:
    13
    So I find something interesting, if I set my dirt tilemap and cave tilemap to be 200-200-0. And render it it stays the same. But when I set the stone tilemap to be 200-200-0 it changes to the height that has been set. But its not a static height it varies around 42-48. and my max height is 48. So all I have to do is figure out how to set the height to a number without messing with the height I want for my tiles..

    Only problem is, I have no clue how to do that. Any help is appreciated. :)
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,689
    Make your max height 480... does the problem go away?

    If it does, pick a smaller size closer to 48 and get on with your life.

    If it doesn't, you know that's not it. Start tracking down other options!