Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Draw grid with vertex height

Discussion in 'Scripting' started by Burton-kun, Aug 9, 2019.

  1. Burton-kun

    Burton-kun

    Joined:
    Aug 6, 2015
    Posts:
    50
    Hi,
    I'm trying to draw a grid on a map, it's a tile based game so I have these tiles and an assigned array of integers rappresenting the tile hight. I need the grid to be adapt to these tiles height and I decided to draw it by vertices in order to have "oblique" tiles between tiles of different hights. I tried anything but i think I lost my self in logic 'cause I can't come out with a solution. The cycles that draw the grid.

    It's a square map with mapSize*mapSize tiles as the array that contains the heights.

    Code (CSharp):
    1.  
    2.  
    3. // These are assigned externally, I write them just for completeness.
    4. int mapSize = value;
    5. int tileSize = value;
    6. int[] heights = new int[mapSize*mapSize];
    7.  
    8. for (int i = 0; i < mapSize; i++)
    9.         {
    10.             for (int j = 0; j < mapSize; j++)
    11.             {
    12.                 int halftile = tileSize / 2;
    13.                 Vector3 tileCenter = new Vector3(i * tileSize, 0, j * tileSize) + new Vector3(halfile, 0, halftile);
    14.              
    15.                 //Tile VerticesT
    16.                 Vector3 v1 = new Vector3(-halftile, 0, -halftile);
    17.                 Vector3 v2 = new Vector3(halftile, 0, -halftile);
    18.                 Vector3 v3 = new Vector3(-halftile, 0, -halftile);
    19.                 Vector3 v4 = new Vector3(-halftile, 0, halftile);
    20.  
    21.                 int leftHeight = 0;
    22.                 int topHeight = 0;
    23.  
    24.                 int height = heights[i * mapSize + j] * tileSize;
    25.  
    26.                 if (i > 0) leftHeight = heights[(i - 1) * mapSize + j] * tileSize;
    27.                 else leftHeight = height;
    28.  
    29.                 if (j > 0) topHeight = heights[i * mapSize + (j-1)] * tileSize;
    30.                 else topHeight = height ;
    31.  
    32.                 v1.y = leftHeight;
    33.                 v2.y = height;
    34.  
    35.                 v3.y = height;
    36.                 v4.y = topHeight;
    37.  
    38.                 Handles.DrawDottedLine(tileCenter + v1, tileCenter + v2, 1);
    39.                 Handles.DrawDottedLine(tileCenter + v3, tileCenter + v4, 1);
    40.  
    41.             }
    42.         }
    43.  
    I draw the grid by drawing just two sides (vertical and horizontal) for each tile, but I can't figure out how the height should be assigned to the vertices. What I'm trying here is assign the height of the previous tile to the last vertice of the line. I kind of get what I want but with a square hill the grid won't match. How could I solve?
     
    Last edited: Aug 9, 2019
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,797
    Based on line 24, it would seem the shallowest angle you can have is 45 degrees, since you are using all integer calculations, and since even one difference in the heights table would trigger a full tileSize change worth of height. Is that your problem?

    I'm also a bit unclear on the if statements in line 26 and 29, but the same thing applies as far as the minimum Y difference being equal to the tileSize, meaning you cannot have a shallow rise in height.
     
  3. Burton-kun

    Burton-kun

    Joined:
    Aug 6, 2015
    Posts:
    50
    Yes, the editor behind works that way: the minium height I can set is one tileSize, you're right on the degree too. The problem is that I get a grid actually, but not every vertice is well placed. I don't know how to assign properly the hight to the vertices. Here what happens:

    capture.PNG

    Don't know if it's clear by the picture, but the blue ones are tiles at a certain height, the red line and all those behind should have both vertices at the same hight at the blue tile. I tried different cunfigurations with no results, maybe it got even worse. I found myself thinking that maybe there was a better way to do that.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,797
    So here's another question: if for each tile iteration you are drawing the top edge and the left edge, shouldn't you only need three verts, not four as you have them? In the pic below the red vert would be used twice...

    only_three_verts.png
     
  5. Burton-kun

    Burton-kun

    Joined:
    Aug 6, 2015
    Posts:
    50
    Yes, you were right. I deleted a vertice. I was trying to calculate two different heights for what were the same vertices. The result is better but I still have problems. I think that just three vertices and two lines won't be enough. But still I can't figure out how to make this work properly.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,797
    Hmm... it really kinda has to be enough, because you get the (i,j) then the (i+1,j), then the (i,j+1), and then move onto the next column and row. Maybe post your current loop code and we can all squint at it together?
     
  7. Burton-kun

    Burton-kun

    Joined:
    Aug 6, 2015
    Posts:
    50
    Of course, thank you for the help, this is the code how it looks right now:

    Code (CSharp):
    1. // These are assigned externally, I write them just for completeness.
    2. int mapSize = value;
    3. int tileSize = value;
    4. int[] heights = new int[mapSize*mapSize];
    5. for (int i = 0; i < mapSize; i++)
    6.         {
    7.             for (int j = 0; j < mapSize; j++)
    8.             {
    9.                 int halftile = tileSize / 2;
    10.                 Vector3 tileCenter = new Vector3(i * tileSize, 0, j * tileSize) + new Vector3(halfile, 0, halftile);
    11.      
    12.                 //Tile Vertices
    13.          
    14.                 Vector3 v1 = new Vector3(-halftile, 0, -halftile);
    15.                 Vector3 v2 = new Vector3(halftile, 0, -halftile);
    16.                 Vector3 v3 = new Vector3(-halftile, 0, halftile);
    17.  
    18.                 int rightHeight = 0;
    19.                 int topHeight = 0;
    20.                 int height = heights[i * mapSize + j] * tileSize;
    21.  
    22.                 if (i < mapSize - 1) rightHeight = heights[(i + 1) * mapSize+ j] * tileSize;
    23.                 else rightHeight = height;
    24.  
    25.                 if (j < mapSize - 1) topHeight = heights[i * mapSize + (j + 1)] * tileSize;
    26.                 else topHeight = height;
    27.  
    28.                 v1.y = height;
    29.                 v2.y = rightHeight;
    30.                 v3.y = topHeight;
    31.  
    32.                 Handles.DrawDottedLine(tile + v1, tile + v2, 1);
    33.                 Handles.DrawDottedLine(tile + v1, tile + v3, 1);
    34.             }
    35.         }
    36.  
    The v1.y is assigned just for "debug". This is actually wrong but I don't know what assign. This is the final result:
    c.png

    As you can see from the cursor in the picture, the tile height does not coincide with the grid. I can imagine why, I'm checking out for the next tile on the right and taking that height. The problem is that I don't know how to fix that. If I choose the left height I will be loose a tile on the other side. I will loose a tile anyway, so I feel a little bit stucked.
     
    Last edited: Aug 10, 2019
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,797
    I think you should make a tiny 2x2 or 3x3 grid of heights and hard-code the positions so you can identify what each vertex is grabbing and figure out where it goes wrong. Everything above looks okay.
     
  9. Burton-kun

    Burton-kun

    Joined:
    Aug 6, 2015
    Posts:
    50
    The main problem is that if I have one vertice between two tiles, one with height 0 and the other one with height 1, which height should I assign to the vertice, 1 or 0? I think that all this bother come from the attempt to assign height to a vertice based on tile height. If my editor assigned height to vertices instead I should not worry so much about how I draw the lines. So I think that I should convert my editor in order to work with vertices, and then just connect them. Or maybe I'm still forgetting something and this whole reasoning is redoundant.

    EDIT:

    I found the solution! I was trying to assign the vert's height by computing just two heights but I needed more. Every vertice is located between three tiles, the one on the left/right, the one on the top/bottom and the one on the diagonal. Since I draw the grid using only three verts i computed three heights for each vert and assigned the highest one, including it's hight.

    I leave the code for anyone may need it in future:

    Code (CSharp):
    1.  
    2. // These are assigned externally, I write them just for completeness.
    3. int mapSize = value;
    4. int tileSize = value;
    5. int[] heights = new int[mapSize*mapSize];
    6.  
    7. for (int i = 0; i < mapSize; i++)
    8.         {
    9.             for (int j = 0; j < mapSize; j++)
    10.             {
    11.                 int halftile = tileSize / 2;
    12.                 // The center of the current tile
    13.                 Vector3 tile = new Vector3(i * tileSize, 0, j * tileSize) + new Vector3(halftile, 0, halftile);
    14.  
    15.                 Vector3 v1 = new Vector3(-halftile, 0, -halftile);
    16.                 Vector3 v2 = new Vector3(halftile, 0, -halftile);
    17.                 Vector3 v3 = new Vector3(-halftile, 0, halftile);
    18.  
    19.                 int lh = 0; //Left Height
    20.                 int rh = 0; //Right Height
    21.                 int th = 0; //Top Height
    22.                 int bh = 0; //Bottom Height
    23.  
    24.                 int lbh = 0; //Left-Bottom Height
    25.                 int lth = 0; //Left-Top Height
    26.                 int rbh = 0; //Right-Bottom Height
    27.  
    28.                 int h = heights[i * mapSize + j] * tileSize;
    29.  
    30.                 if (i < mapSize - 1) rh = heights[(i + 1) * mapSize+ j] * tileSize;
    31.                 if (j < mapSize - 1) th = map.heights[i * mapSize + (j + 1)] * tileSize;
    32.                 if (i > 0) lh = heights[(i - 1) * mapSize + j] * tileSize;
    33.                 if (j > 0) bh = heights[i * mapSize+ (j - 1)] * tileSize;
    34.  
    35.                 if (i > 0 && j > 0) lbh = heights[(i - 1) * mapSize + (j - 1)] * tileSize;
    36.                 if (i > 0 && j < mapSize- 1) lth = heights[(i - 1) * mapSize + (j + 1)] * tileSize;
    37.                 if (i < mapSize - 1 && j > 0) rbh = heights[(i + 1) * mapSize+ (j - 1)] * tileSize;
    38.  
    39.                 v1.y = Mathf.Max(h, Mathf.Max(lbh, Mathf.Max(lh, bh)));
    40.                 v2.y = Mathf.Max(h, Mathf.Max(rbh, Mathf.Max(rh, bh)));
    41.                 v3.y = Mathf.Max(h, Mathf.Max(lth, Mathf.Max(lh, th)));
    42.  
    43.                 Handles.DrawDottedLine(tile + v1, tile + v2, 1);
    44.                 Handles.DrawDottedLine(tile + v1, tile + v3, 1);
    45.             }
    46.         }
    Thank you Kurt-Dekker for the help :D
     
    Last edited: Aug 10, 2019
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,797
    You're welcome. Good find on the solution, using all three to get your height correctly calculated!
     
    Burton-kun likes this.