Search Unity

Procedural Cave Generation

Discussion in 'Community Learning & Teaching' started by SebastianLague, Feb 9, 2015.

  1. _Eyesgood_

    _Eyesgood_

    Joined:
    Apr 19, 2013
    Posts:
    55
    Excellent cefwyn! That helps a ton! Thanks!
     
  2. ahmalt

    ahmalt

    Joined:
    Mar 1, 2016
    Posts:
    1
    Hello everyone
    i am still in my first step in this awsome tutorial but I have a problem, strangly the map doesn't show even tough I made sure the code is correct and every thing is set up like the tutorial (the first video). i am supposing that it's a camera problem. have you ever encountered this problem? all i get is the blue color of the camera, I tried to change the position of the camera several times but nothing seams to work; i am working on the latest version of unity, and I couldn't figure out the problem causes
     
  3. Dustin-Howard

    Dustin-Howard

    Joined:
    Mar 31, 2016
    Posts:
    12
    I'm done with all the steps except for the last video.
    I'm struggling a bit with some parts, so I'm asking like what should be the details of each game object?
    Example: Main Camera should be centered at transfer, rotation, and scale.
    Another Example: The Player Game Object should have the transform of: , the rigidbody should have the following details:

    I may be asking a false question, but I'm really stressing out here.
    Thanks
     
  4. Hveorungr

    Hveorungr

    Joined:
    Sep 27, 2014
    Posts:
    1
    Hello everyone,

    I really love this tutorial and I was actually trying to put some objects on the walls created. But obviously I need to code it cause of the random generation. So I tried to get a random point on the wall and get 3 triangles linked to my point. And get all 3 normal of those 3 triangles in order to get a perpendicular line and put my object nicely on the wall but it seems my method doesn't work.

    Do you have another solution in order to get the normal of a random vertice of the wall ?
    Thanks
     
  5. ChromeLynx

    ChromeLynx

    Joined:
    May 27, 2016
    Posts:
    1
    At the end of episode 4, my system never generated walls. I keep getting ArgumentOutOfRangeExceptions originating from a file outside of the work, it seems. Is there a workaround or am I stuck forever when it comes to walls?
     
  6. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    I think it would be better if you put some comments in your code explaining concepts. Just a thought. :)
     
  7. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    Can someone please explain part one of the tutorial to me? I have watched the video twice and I am still confused.
     
  8. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    Technically, it only works for authentic randomization, not pseudo randomization, so the use random seed bool won't be used.

    Also, what is the point of setting the seed to some value if using Random.Range()?
     
  9. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    One concept I don't understand in the Celluar Automato is why do we call the Smoothing function many times? I mean, I understand that it makes the map smoother with less black holes in the middle of white space but why does this happen. I don't understand why the map becomes smoother when calling the Smoothing function more times. please help o_O
     
  10. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    I have completed episode two but I don't completely understand the code. Can someone explain what is going on here? :confused:
     
  11. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    How come you get to set an integer to an integer array with no specified parameter in the array.

    In this example, nodeCountX and nodeCountY are integers that we are setting to a dimension of the array with no parameter in the dimension:

    Code (CSharp):
    1.  public SquareGrid(int[,] map, float squareSize) //Setting the argument to equal the two dimensional array map and the square size.
    2.         {
    3.             int nodeCountX = map.GetLength(0); //This is node CountX.
    4.             int nodeCountY = map.GetLength(1); //This is nodeCounty.
    5.             float mapWidth = nodeCountX * squareSize;
    6.             float mapHeight = nodeCountY * squareSize;
    7.  
     
  12. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    There is a weird bug in the project. When testing in the scene, I looked at my map and suddenly after a few seconds, the map dissapeared. I recently just finished part two of the tutorial and didnt start part three.
     
  13. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :)Check in the Scene Mode not in the Game Mode. A gizmo is only visible in Scene Mode not Game View. Click the game view to generate a new random image, but the actual image is in the scene view.
     
  14. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    o_O What do we use the vertex index in the Node class for?
     
  15. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    ;) How did you come up with this position?

    Code (CSharp):
    1.  Vector3 pos = new Vector3(-mapWidth / 2 + x * squareSize, 0, -mapHeight + y * squareSize);
    To be more clear, what is the purpose of -mapWidth/2 and -mapHeight/2?
     
    Last edited: Jun 9, 2016
  16. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    ;) I just completed part 3. Can someone explain what is happening? Not exactly sure what is happening.
     
  17. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :eek: At part 4, the walls do not show up. I looked at my console and saw a

    KeyNotFoundException: The given key was not present in the dictionary.
    System.Collections.Generic.Dictionary`2[System.Int32,System.Collections.Generic.List`1[MeshGenerator+Triangle]].get_Item (Int32 key) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:150)
    MeshGenerator.GetConnectedOutlineVertex (Int32 vertexIndex) (at Assets/MeshGenerator.cs:231)
    MeshGenerator.CalculateMeshOutlines () (at Assets/MeshGenerator.cs:203)
    MeshGenerator.CreateWallMesh () (at Assets/MeshGenerator.cs:43)
    MeshGenerator.GenerateMesh (System.Int32[,] map, Single squareSize) (at Assets/MeshGenerator.cs:35)
    MapGenerator.GenerateMap () (at Assets/MapGenerator.cs:52)
    MapGenerator.Start () (at Assets/MapGenerator.cs:18)


    error. What should I do?
     
  18. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    o_O Ok. Finally, I fixed the KeyNotFoundException Error but when I generate the walls, only some walls are partially generated. Others are not generated.


    upload_2016-6-9_18-18-3.png
     
  19. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :( Here is my code for part 4. I don't get what's wrong:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class MeshGenerator : MonoBehaviour
    6. {
    7.  
    8.     public SquareGrid squareGrid;
    9.     public MeshFilter walls;
    10.     List<Vector3> vertices;
    11.     List<int> triangles;
    12.  
    13.     List<List<int>> outlines = new List<List<int>>();
    14.     Dictionary<int, List<Triangle>> triangleDictionary = new Dictionary<int, List<Triangle>>();
    15.     HashSet<int> checkedVertices = new HashSet<int>();
    16.     public void GenerateMesh(int[,] map, float squareSize)
    17.     {
    18.         triangleDictionary.Clear();
    19.         outlines.Clear();
    20.         checkedVertices.Clear();
    21.  
    22.         vertices = new List<Vector3>();
    23.         triangles = new List<int>();
    24.         squareGrid = new SquareGrid(map, squareSize);
    25.         for (int x = 0; x < squareGrid.squares.GetLength(0); x++)
    26.         {
    27.             for (int y = 0; y < squareGrid.squares.GetLength(1); y++)
    28.             {
    29.                 TriangulateSquare(squareGrid.squares[x, y]);
    30.             }
    31.         }
    32.         Mesh mesh = new Mesh();
    33.         GetComponent<MeshFilter>().mesh = mesh;
    34.         mesh.vertices = vertices.ToArray();
    35.         mesh.triangles = triangles.ToArray();
    36.         mesh.RecalculateNormals();
    37.         CreateWallMesh();
    38.  
    39.  
    40.     }
    41.  
    42.     void CreateWallMesh()
    43.     {
    44.  
    45.         CalculateMeshOutlines();
    46.         List<Vector3> wallVertices = new List<Vector3>();
    47.         List<int> wallTriangles = new List<int>();
    48.         Mesh wallMesh = new Mesh();
    49.         float wallHeight = 5;
    50.  
    51.         foreach (List<int> outline in outlines)
    52.         {
    53.  
    54.             for (int i = 0; i < outline.Count - 1; i++)
    55.             {
    56.                 int startIndex = wallVertices.Count;
    57.                 wallVertices.Add(vertices[outline[i]]); //left
    58.  
    59.                 wallVertices.Add(vertices[outline[i + 1]]);//right
    60.  
    61.                 wallVertices.Add(vertices[outline[i]] - Vector3.up * wallHeight); //bottom left
    62.  
    63.                 wallVertices.Add(vertices[outline[i + 1]] - Vector3.up * wallHeight); // bottom right
    64.  
    65.  
    66.                 wallTriangles.Add(startIndex + 0);
    67.                 wallTriangles.Add(startIndex + 2);
    68.                 wallTriangles.Add(startIndex + 3);
    69.  
    70.                 wallTriangles.Add(startIndex + 3);
    71.                 wallTriangles.Add(startIndex + 1);
    72.                 wallTriangles.Add(startIndex + 0);
    73.             }
    74.         }
    75.         wallMesh.vertices = wallVertices.ToArray();
    76.         wallMesh.triangles = wallTriangles.ToArray();
    77.         walls.mesh = wallMesh;
    78.     }
    79.     void TriangulateSquare(Square square)
    80.     {
    81.         switch (square.configuration)
    82.         {
    83.         case 0:
    84.             break;
    85.             //1 points
    86.         case 1:
    87.             MeshFromPoints(square.centreLeft, square.centreBottom, square.bottomLeft);
    88.             break;
    89.         case 2:
    90.             MeshFromPoints(square.bottomRight, square.centreBottom, square.centreRight);
    91.             break;
    92.         case 4:
    93.             MeshFromPoints(square.topRight, square.centreRight, square.centreTop);
    94.             break;
    95.         case 8:
    96.             MeshFromPoints(square.topLeft, square.centreTop, square.centreLeft);
    97.             break;
    98.  
    99.             //2 points
    100.  
    101.         case 3:
    102.             MeshFromPoints(square.centreRight, square.bottomRight, square.bottomLeft, square.centreLeft);
    103.             break;
    104.         case 6:
    105.             MeshFromPoints(square.centreTop, square.topRight, square.bottomRight, square.centreBottom);
    106.             break;
    107.         case 9:
    108.             MeshFromPoints(square.topLeft, square.centreTop, square.centreBottom, square.bottomLeft);
    109.             break;
    110.         case 12:
    111.             MeshFromPoints(square.topLeft, square.topRight, square.centreRight, square.centreLeft);
    112.             break;
    113.         case 5:
    114.             MeshFromPoints(square.centreTop, square.topRight, square.centreRight, square.centreBottom, square.bottomLeft, square.centreLeft);
    115.             break;
    116.         case 10:
    117.             MeshFromPoints(square.topLeft, square.centreTop, square.centreRight, square.bottomRight, square.centreBottom, square.centreLeft);
    118.             break;
    119.  
    120.             // 3 points
    121.         case 7:
    122.             MeshFromPoints(square.centreTop, square.topRight, square.bottomRight, square.bottomLeft, square.centreLeft);
    123.             break;
    124.         case 11:
    125.             MeshFromPoints(square.topLeft, square.centreTop, square.centreRight, square.bottomRight, square.bottomLeft);
    126.             break;
    127.         case 13:
    128.             MeshFromPoints(square.topLeft, square.topRight, square.centreRight, square.centreBottom, square.bottomLeft);
    129.             break;
    130.         case 14:
    131.             MeshFromPoints(square.topLeft, square.topRight, square.bottomRight, square.centreBottom, square.centreLeft);
    132.             break;
    133.             //4 points
    134.         case 15:
    135.             MeshFromPoints(square.topLeft, square.topRight, square.bottomRight, square.bottomLeft);
    136.             checkedVertices.Add(square.topLeft.vertexIndex);
    137.             checkedVertices.Add(square.topRight.vertexIndex);
    138.             checkedVertices.Add(square.bottomRight.vertexIndex);
    139.             checkedVertices.Add(square.bottomLeft.vertexIndex);
    140.             break;
    141.  
    142.         }
    143.  
    144.     }
    145.  
    146.     void MeshFromPoints(params Node[] points)
    147.     {
    148.         AssignVertices(points);
    149.         if (points.Length >= 3)
    150.             CreateTriangle(points[0], points[1], points[2]);
    151.         if (points.Length >= 4)
    152.             CreateTriangle(points[0], points[2], points[3]);
    153.         if (points.Length >= 5)
    154.             CreateTriangle(points[0], points[3], points[4]);
    155.         if (points.Length >= 6)
    156.             CreateTriangle(points[0], points[4], points[5]);
    157.     }
    158.     void AssignVertices(Node[] points)
    159.     {
    160.         for (int i = 0; i < points.Length; i++)
    161.         {
    162.             if (points[i].vertexIndex == -1)
    163.             {
    164.                 points[i].vertexIndex = vertices.Count;
    165.                 vertices.Add(points[i].position);
    166.             }
    167.         }
    168.     }
    169.  
    170.     void CreateTriangle(Node a, Node b, Node c)
    171.     {
    172.         triangles.Add(a.vertexIndex);
    173.         triangles.Add(b.vertexIndex);
    174.         triangles.Add(c.vertexIndex);
    175.  
    176.         Triangle triangle = new Triangle(a.vertexIndex, b.vertexIndex, c.vertexIndex);
    177.  
    178.         AddTriangleToDictionary(triangle.vertexIndexA, triangle);
    179.         AddTriangleToDictionary(triangle.vertexIndexB, triangle);
    180.         AddTriangleToDictionary(triangle.vertexIndexC, triangle);
    181.     }
    182.  
    183.     void AddTriangleToDictionary(int vertexIndex, Triangle triangle)
    184.     {
    185.         if (triangleDictionary.ContainsKey(vertexIndex))
    186.         {
    187.             triangleDictionary[vertexIndex].Add(triangle);
    188.         }
    189.         else{
    190.             List<Triangle> triangleList = new List<Triangle> ();
    191.             triangleList.Add (triangle);
    192.             triangleDictionary.Add (vertexIndex, triangleList);
    193.  
    194.         }
    195.     }
    196.  
    197.     void CalculateMeshOutlines()
    198.     {
    199.  
    200.         for (int vertexIndex = 0; vertexIndex < vertices.Count; vertexIndex++)
    201.         {
    202.  
    203.             if (!checkedVertices.Contains(vertexIndex))
    204.             {
    205.  
    206.                 int newOutlineVertex = GetConnectedOutlineVertex(vertexIndex);
    207.                 if (newOutlineVertex != -1)
    208.                 {
    209.                     checkedVertices.Add(vertexIndex);
    210.  
    211.                     List<int> newOutline = new List<int>();
    212.                     newOutline.Add(vertexIndex);
    213.                     outlines.Add(newOutline);
    214.                     FollowOutline(newOutlineVertex, outlines.Count - 1);
    215.                     outlines[outlines.Count - 1].Add(vertexIndex);
    216.                 }
    217.             }
    218.         }
    219.     }
    220.  
    221.     void FollowOutline(int vertexIndex, int outlineIndex)
    222.     {
    223.         outlines[outlineIndex].Add(vertexIndex);
    224.         checkedVertices.Add(vertexIndex);
    225.         int nextVertexIndex = GetConnectedOutlineVertex(vertexIndex);
    226.         if (nextVertexIndex != -1)
    227.         {
    228.             FollowOutline(nextVertexIndex, outlineIndex);
    229.         }
    230.     }
    231.  
    232.     int GetConnectedOutlineVertex(int vertexIndex) {
    233.  
    234.         List<Triangle> trianglesContainingVertex = triangleDictionary[vertexIndex];
    235.  
    236.         for (int i = 0; i < trianglesContainingVertex.Count; i++)
    237.         {
    238.             Triangle triangle = trianglesContainingVertex[i];
    239.  
    240.             for (int j = 0; j < 3; j++)
    241.             {
    242.                 int vertexB = triangle[j];
    243.                 if (vertexB != vertexIndex && !checkedVertices.Contains(vertexB))
    244.                     return vertexB;
    245.             }
    246.         }
    247.         return -1;
    248.     }
    249.  
    250.     bool IsOutlineEdge(int vertexA, int vertexB)
    251.     {
    252.         List<Triangle> trianglesContainingVertexA = triangleDictionary[vertexA];
    253.         int sharedTriangleCount = 0;
    254.  
    255.         for (int i = 0; i < trianglesContainingVertexA.Count; i++)
    256.         {
    257.             if (trianglesContainingVertexA[i].Contains(vertexB))
    258.             {
    259.                 sharedTriangleCount++;
    260.                 if (sharedTriangleCount > 1)
    261.                 {
    262.  
    263.                     break;
    264.                 }
    265.             }
    266.         }
    267.  
    268.         return sharedTriangleCount == 1;
    269.     }
    270.  
    271.     struct Triangle
    272.     {
    273.         public int vertexIndexA;
    274.         public int vertexIndexB;
    275.         public int vertexIndexC;
    276.         int[] vertices;
    277.  
    278.         public Triangle(int a, int b, int c)
    279.         {
    280.             vertexIndexA = a;
    281.             vertexIndexB = b;
    282.             vertexIndexC = c;
    283.             vertices = new int[3];
    284.             vertices[0] = a;
    285.             vertices[1] = b;
    286.             vertices[2] = c;
    287.         }
    288.  
    289.         public int this[int i]
    290.         {
    291.             get
    292.             {
    293.                 return vertices[i];
    294.             }
    295.         }
    296.  
    297.         public bool Contains(int vertexIndex)
    298.         {
    299.             return vertexIndex == vertexIndexA || vertexIndex == vertexIndexB || vertexIndex == vertexIndexC;
    300.         }
    301.     }
    302.  
    303.  
    304.     public class SquareGrid
    305.     {
    306.         public Square[,] squares;
    307.  
    308.         public SquareGrid(int[,] map, float squareSize)
    309.         {
    310.             int nodeCountX = map.GetLength(0);
    311.             int nodeCountY = map.GetLength(1);
    312.             float mapWidth = nodeCountX * squareSize;
    313.             float mapHeight = nodeCountY * squareSize;
    314.  
    315.             ControlNode[,] controlNodes = new ControlNode[nodeCountX, nodeCountY];
    316.  
    317.             for (int x = 0; x < nodeCountX; x++)
    318.             {
    319.                 for (int y = 0; y < nodeCountY; y++)
    320.                 {
    321.                     Vector3 pos = new Vector3(-mapWidth / 2 + x * squareSize, 0, -mapHeight + y * squareSize);
    322.                     controlNodes[x, y] = new ControlNode(pos, map[x, y] == 1, squareSize);
    323.                 }
    324.             }
    325.  
    326.             squares = new Square[nodeCountX - 1, nodeCountY - 1];
    327.             for (int x = 0; x < nodeCountX - 1; x++)
    328.             {
    329.                 for (int y = 0; y < nodeCountY - 1; y++)
    330.                 {
    331.                     squares[x, y] = new Square(controlNodes[x, y + 1], controlNodes[x + 1, y + 1], controlNodes[x + 1, y], controlNodes[x, y]);
    332.                 }
    333.             }
    334.         }
    335.     }
    336.  
    337.     public class Square
    338.     {
    339.         public ControlNode topLeft, topRight, bottomRight, bottomLeft;
    340.         public Node centreTop, centreRight, centreBottom, centreLeft;
    341.         public int configuration;
    342.  
    343.         public Square(ControlNode _topLeft, ControlNode _topRight, ControlNode _bottomRight, ControlNode _bottomLeft)
    344.         {
    345.             topLeft = _topLeft;
    346.             topRight = _topRight;
    347.             bottomRight = _bottomRight;
    348.             bottomLeft = _bottomLeft;
    349.  
    350.             centreTop = topLeft.right;
    351.             centreRight = bottomRight.above;
    352.             centreBottom = bottomLeft.right;
    353.             centreLeft = bottomLeft.above;
    354.  
    355.             if (topLeft.active)
    356.                 configuration += 8;
    357.             if (topRight.active)
    358.                 configuration += 4;
    359.             if (bottomRight.active)
    360.                 configuration += 2;
    361.             if (bottomLeft.active)
    362.                 configuration += 1;
    363.         }
    364.  
    365.     }
    366.  
    367.  
    368.     public class Node
    369.     {
    370.         public Vector3 position;
    371.         public int vertexIndex = -1;
    372.  
    373.  
    374.         public Node(Vector3 _pos)
    375.         {
    376.             position = _pos;
    377.         }
    378.     }
    379.     public class ControlNode : Node
    380.     {
    381.         public bool active;
    382.         public Node above, right;
    383.         public ControlNode(Vector3 _pos, bool _active, float squareSize) : base(_pos)
    384.         {
    385.             active = _active;
    386.             above = new Node(position + Vector3.forward * squareSize / 2);
    387.             right = new Node(position + Vector3.right * squareSize / 2);
    388.         }
    389.     }
    390.  
    391. }
    392.  
     
  20. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :mad: When I was trying to copy and paste a snippet of code from the website, the copy and paste button won't work. It would actually just post some random sort of jibberish. Is this a glitch? Should I report it? Or is just my computer?
     
  21. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :( After some fixing, I got this
    upload_2016-6-9_21-0-54.png



    However, when I look at the sides, I saw there were holes in the wall.


    What did I goof up in?

    Edit: I realized that the completed code bit(from the website) also gives the same results. I will just ingnore this glitch then.
     
    Last edited: Jun 10, 2016
  22. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    o_O Ok, finally I completed part 4 of the tutorial. However, I don't understand literally anything of the tutorial( kinda hilarious ;)). Can someone please explain it to me?
     
  23. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :confused: I don't understand this clockwise thing in the beginning of the video. At 1:40, shouldn't the direction of the outline go from A-B. Isn't that clockwise?

    Edit: :eek: Wait a minute. Does this clockwise thing work like this: start from one point, make a line to another point to create the hypotenuse of the triangle, and then go to the last point and back again to the first point to create a triangle?
     
    Last edited: Jun 10, 2016
  24. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    o_O How does this piece of code keep the coordinates inside the border instead of outside the border?


    Code (CSharp):
    1.  if(x>=borderedSize && x<width+borderedSize && y>=borderedSize && y < height + borderedSize)
    2.                 {
    3.                     borderedMap[x, y] = map[x - borderedSize, y - borderedSize];
    4.                 }
    Edit: I get why we do the x>=borderedSize and y>=bordered size, because if we don't do that code, we can get errors in this code:
    Code (CSharp):
    1.   borderedMap[x, y] = map[x - borderedSize, y - borderedSize];
    as x-borered size and y-bordered size might result errors since there are no negative values in an array.


    Still I don't understand the x<width+borderedSize and y<height+bordered Size. technacially shouldnt it be x<=width and y<=height as the bordered size is supposed to be the border not part of the map?
     
    Last edited: Jun 10, 2016
  25. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :eek: I don't understand this piece of code:
    Code (CSharp):
    1. public int this[int i]
    2.         {
    3.             get
    4.             {
    5.                 return vertices[i];
    6.             }
    7.         }
     
  26. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :confused: I don't get this code bit:

    Code (CSharp):
    1. int vertexB = triangle [j];
    What are we setting vertexB to equal to. P.S. why is it called vertexB instead of vertex.
     
  27. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    o_O Why do we call Add triangle to dictionary three times when we create a triangle. WOn't this add three triangles to the dictionary instead of only one when creating a new triangle?

    Code (CSharp):
    1. void CreateTriangle(Node a, Node b, Node c) {
    2.         triangles.Add(a.vertexIndex);
    3.         triangles.Add(b.vertexIndex);
    4.         triangles.Add(c.vertexIndex);
    5.  
    6.         Triangle triangle = new Triangle (a.vertexIndex, b.vertexIndex, c.vertexIndex);
    7.         AddTriangleToDictionary (triangle.vertexIndexA, triangle);
    8.         AddTriangleToDictionary (triangle.vertexIndexB, triangle);
    9.         AddTriangleToDictionary (triangle.vertexIndexC, triangle);
    10.     }
     
  28. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :mad: I don't get this at all:

    Code (CSharp):
    1. if (vertexB != vertexIndex && !checkedVertices.Contains(vertexB)) {
    2.                     if (IsOutlineEdge(vertexIndex, vertexB)) {
    3.                         return vertexB;
    4.                     }
    5.                 }
    what is the first if statement for?
     
  29. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :cool: Ok guys, I finally understood part 4 of the tutorial by rewatching the whole tutorial and paying attention to it without coding. However, still don't understand this code bit:


    Code (CSharp):
    1.  if(x>=borderedSize && x<width+borderedSize && y>=borderedSize && y < height + borderedSize)
    2.                 {
    3.                     borderedMap[x, y] = map[x - borderedSize, y - borderedSize];
    4.                 }
     
  30. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :( Ok guys, when ever I compile my code, the wall threshold size turns out to kill a lot of walls. It kills much more walls than the tutorial. Why is this happening? I'm on part 5 of the tutorial.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class MapGenerator : MonoBehaviour
    6. {
    7.     public int width;
    8.     public int height;
    9.  
    10.  
    11.     [Range(0, 100)]
    12.     public int randFillPercent;
    13.  
    14.     int[,] map;
    15.  
    16.     void Start()
    17.     {
    18.         GenerateMap();
    19.     }
    20.     void Update()
    21.     {
    22.         if (Input.GetMouseButtonDown(0))
    23.         {
    24.             GenerateMap();
    25.         }
    26.     }
    27.     void GenerateMap()
    28.     {
    29.         map = new int[width, height];
    30.         RandomFillMap();
    31.         for (int i = 0; i < 5; i++)
    32.         {
    33.             SmoothMap();
    34.         }
    35.  
    36.         ProcessMap ();
    37.  
    38.         int borderedSize = 1;
    39.         int[,] borderedMap = new int[width + borderedSize * 2, height + borderedSize * 2];
    40.         for (int x = 0; x < borderedMap.GetLength(0); x++)
    41.         {
    42.             for (int y = 0; y < borderedMap.GetLength(1); y++)
    43.             {
    44.                 if(x>=borderedSize && x<width+borderedSize && y>=borderedSize && y < height + borderedSize)
    45.                 {
    46.                     borderedMap[x, y] = map[x - borderedSize, y - borderedSize];
    47.                 }
    48.                 else
    49.                 {
    50.                     borderedMap[x, y] = 1;
    51.                 }
    52.             }
    53.         }
    54.         MeshGenerator meshGen = GetComponent<MeshGenerator>();
    55.         meshGen.GenerateMesh(borderedMap, 1);
    56.     }
    57.  
    58.     void ProcessMap(){
    59.         List<List<Coord>> wallRegions = GetRegions (1);
    60.         int wallThresoldSize =50;
    61.  
    62.         foreach (List<Coord> wallRegion in wallRegions) {
    63.             if (wallRegion.Count < wallThresoldSize) {
    64.                 foreach (Coord tile in wallRegion) {
    65.                     map [tile.tileX, tile.tileY] = 0;
    66.                 }
    67.             }
    68.         }
    69.  
    70.         List<List<Coord>> roomRegions = GetRegions (0);
    71.         int roomThresoldSize = 50;
    72.  
    73.         foreach (List<Coord> roomRegion in roomRegions) {
    74.             if (roomRegion.Count < roomThresoldSize) {
    75.                 foreach (Coord tile in roomRegion) {
    76.                     map [tile.tileX, tile.tileY] = 1;
    77.                 }
    78.             }
    79.  
    80.         }
    81.  
    82.     }
    83.  
    84.  
    85.     List<List<Coord>> GetRegions(int tileType){
    86.         List<List<Coord>> regions = new List<List<Coord>> ();
    87.         int[,] mapFlags = new int[width, height];
    88.  
    89.         for (int x = 0; x < width; x++) {
    90.             for (int y = 0; y < height; y++) {
    91.                 if (mapFlags [x, y] == 0 && map [x, y] == tileType) {
    92.                     List<Coord> newRegion = GetRegionTiles (x, y);
    93.                     regions.Add (newRegion);
    94.  
    95.                     foreach(Coord tile in newRegion){
    96.                         mapFlags [tile.tileX, tile.tileY] = 1;
    97.  
    98.                     }
    99.  
    100.  
    101.                 }
    102.  
    103.             }
    104.  
    105.         }
    106.         return regions;
    107.     }
    108.  
    109.  
    110.  
    111.     List<Coord> GetRegionTiles(int startX, int startY) {
    112.         List<Coord> tiles= new List<Coord>();
    113.         int[,] mapFlags = new int[width, height];
    114.         int tileType = map [startX, startY];
    115.  
    116.         Queue<Coord> queue = new Queue<Coord> ();
    117.         queue.Enqueue(new Coord(startX,startY));
    118.         mapFlags [startX, startY] = 1;
    119.  
    120.         while (queue.Count > 0) {
    121.             Coord tile = queue.Dequeue();
    122.             tiles.Add (tile);
    123.  
    124.             for (int x = tile.tileX-1; x <=tile.tileX+1; x++) {
    125.                 for (int y = tile.tileY-1; y <=tile.tileY+1; y++) {
    126.                     if (IsInMapRange (x, y) && (y == startY || x == startX)) {
    127.                         if (mapFlags [x, y] == 0 && map [x, y] == tileType) {
    128.                             mapFlags [x, y] = 1;
    129.                             queue.Enqueue (new Coord (x, y));
    130.  
    131.                         }
    132.  
    133.                     }
    134.  
    135.                 }
    136.             }
    137.         }
    138.         return tiles;
    139.     }
    140.  
    141.     bool IsInMapRange( int x, int y){
    142.  
    143.         return x >= 0 && x < width && y >= 0 && y < height;
    144.  
    145.     }
    146.  
    147.  
    148.  
    149.     void RandomFillMap()
    150.     {
    151.  
    152.         for (int x = 0; x < width; x++)
    153.         {
    154.             for (int y = 0; y < height; y++)
    155.             {
    156.                 if (x == 0 || x == width - 1 || y == 0 || y == height - 1)
    157.                 {
    158.                     map[x, y] = 1;
    159.  
    160.  
    161.                 }
    162.                 else {
    163.                     map[x, y] = (Random.Range(0, 100) < randFillPercent) ? 1 : 0;
    164.  
    165.                 }
    166.             }
    167.         }
    168.     }
    169.  
    170.     void SmoothMap()
    171.     {
    172.         for (int x = 0; x < width; x++)
    173.         {
    174.             for (int y = 0; y < height; y++)
    175.             {
    176.                 int neighborHoodTiles = GetSurrondingWallCount(x, y);
    177.  
    178.                 if (neighborHoodTiles > 4)
    179.                 {
    180.                     map[x, y] = 1;
    181.                 }
    182.                 else if (neighborHoodTiles < 4)
    183.                 {
    184.                     map[x, y] = 0;
    185.                 }
    186.             }
    187.         }
    188.     }
    189.  
    190.     int GetSurrondingWallCount(int gridX, int gridY)
    191.     {
    192.         int wallCount = 0;
    193.         for (int neighborX = gridX - 1; neighborX <= gridX + 1; neighborX++)
    194.         {
    195.             for (int neighborY = gridY - 1; neighborY <= gridY + 1; neighborY++)
    196.             {
    197.                 if (IsInMapRange(neighborX, neighborY) )
    198.                 {
    199.                     if (neighborX != gridX || neighborY != gridY)
    200.                     {
    201.                         wallCount += map[neighborX, neighborY];
    202.  
    203.                     }
    204.  
    205.                 }
    206.                 else
    207.                 {
    208.                     wallCount++;
    209.                 }
    210.             }
    211.         }
    212.         return wallCount;
    213.     }
    214.  
    215.     struct Coord{
    216.         public int tileX;
    217.         public int tileY;
    218.  
    219.         public Coord(int x, int y){
    220.             tileX=x;
    221.             tileY=y;
    222.  
    223.  
    224.         }
    225.  
    226.     }
    227.  
    228.  
    229. }
    230.  
     
  31. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :( Ok, I finished part 5. However, when I was watching part 6, I got confused on one part. I was also confused on this part many times before( and I think I posted this earlier).

    Code Bit:

    Code (CSharp):
    1.   return new Vector3 (-width / 2 + .5f + tile.tileX, 2, -height / 2 + .5f + tile.tileY);
    how did Sebastian get these coordinates?

    (P.S. I am still confused on this code bit too

    Code (CSharp):
    1. if(x>=borderedSize && x<width+borderedSize && y>=borderedSize && y < height + borderedSize)
    Why are we setting x and y to be less than width or height plus bordered size, shouldn't it be x<=width and y<=height so the coordinates are included inside the map, not in the borders?)
     
  32. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    o_O How can we do this code( I'm on part 6 btw)

    Code (CSharp):
    1.   Room.ConnectRooms (roomA, roomB);
    Don't we have to have an object to do this? How can the class do this by itself. I aplogize if I sound like a noob. I am kinda advanced in coding in C# though. How is this code possible?
     
  33. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :confused: im on part 6 of the tutorial and when I tested the thing at the end of the video, everything went wrong.. I even copied the sample code from the website and posted it into the code and it still went weird.

    Code from the website:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System;
    5.  
    6. public class MapGenerator : MonoBehaviour {
    7.  
    8.     public int width;
    9.     public int height;
    10.  
    11.     public string seed;
    12.     public bool useRandomSeed;
    13.  
    14.     [Range(0,100)]
    15.     public int randomFillPercent;
    16.  
    17.     int[,] map;
    18.  
    19.     void Start() {
    20.         GenerateMap();
    21.     }
    22.  
    23.     void Update() {
    24.         if (Input.GetMouseButtonDown(0)) {
    25.             GenerateMap();
    26.         }
    27.     }
    28.  
    29.     void GenerateMap() {
    30.         map = new int[width,height];
    31.         RandomFillMap();
    32.  
    33.         for (int i = 0; i < 5; i ++) {
    34.             SmoothMap();
    35.         }
    36.  
    37.         ProcessMap ();
    38.  
    39.         int borderSize = 1;
    40.         int[,] borderedMap = new int[width + borderSize * 2,height + borderSize * 2];
    41.  
    42.         for (int x = 0; x < borderedMap.GetLength(0); x ++) {
    43.             for (int y = 0; y < borderedMap.GetLength(1); y ++) {
    44.                 if (x >= borderSize && x < width + borderSize && y >= borderSize && y < height + borderSize) {
    45.                     borderedMap[x,y] = map[x-borderSize,y-borderSize];
    46.                 }
    47.                 else {
    48.                     borderedMap[x,y] =1;
    49.                 }
    50.             }
    51.         }
    52.  
    53.         MeshGenerator meshGen = GetComponent<MeshGenerator>();
    54.         meshGen.GenerateMesh(borderedMap, 1);
    55.     }
    56.  
    57.     void ProcessMap() {
    58.         List<List<Coord>> wallRegions = GetRegions (1);
    59.         int wallThresholdSize = 50;
    60.  
    61.         foreach (List<Coord> wallRegion in wallRegions) {
    62.             if (wallRegion.Count < wallThresholdSize) {
    63.                 foreach (Coord tile in wallRegion) {
    64.                     map[tile.tileX,tile.tileY] = 0;
    65.                 }
    66.             }
    67.         }
    68.  
    69.         List<List<Coord>> roomRegions = GetRegions (0);
    70.         int roomThresholdSize = 50;
    71.         List<Room> survivingRooms = new List<Room> ();
    72.  
    73.         foreach (List<Coord> roomRegion in roomRegions) {
    74.             if (roomRegion.Count < roomThresholdSize) {
    75.                 foreach (Coord tile in roomRegion) {
    76.                     map[tile.tileX,tile.tileY] = 1;
    77.                 }
    78.             }
    79.             else {
    80.                 survivingRooms.Add(new Room(roomRegion, map));
    81.             }
    82.         }
    83.  
    84.         ConnectClosestRooms (survivingRooms);
    85.     }
    86.  
    87.     void ConnectClosestRooms(List<Room> allRooms) {
    88.  
    89.         int bestDistance = 0;
    90.         Coord bestTileA = new Coord ();
    91.         Coord bestTileB = new Coord ();
    92.         Room bestRoomA = new Room ();
    93.         Room bestRoomB = new Room ();
    94.         bool possibleConnectionFound = false;
    95.  
    96.         foreach (Room roomA in allRooms) {
    97.             possibleConnectionFound = false;
    98.  
    99.             foreach (Room roomB in allRooms) {
    100.                 if (roomA == roomB) {
    101.                     continue;
    102.                 }
    103.                 if (roomA.IsConnected(roomB)) {
    104.                     possibleConnectionFound = false;
    105.                     break;
    106.                 }
    107.  
    108.                 for (int tileIndexA = 0; tileIndexA < roomA.edgeTiles.Count; tileIndexA ++) {
    109.                     for (int tileIndexB = 0; tileIndexB < roomB.edgeTiles.Count; tileIndexB ++) {
    110.                         Coord tileA = roomA.edgeTiles[tileIndexA];
    111.                         Coord tileB = roomB.edgeTiles[tileIndexB];
    112.                         int distanceBetweenRooms = (int)(Mathf.Pow (tileA.tileX-tileB.tileX,2) + Mathf.Pow (tileA.tileY-tileB.tileY,2));
    113.  
    114.                         if (distanceBetweenRooms < bestDistance || !possibleConnectionFound) {
    115.                             bestDistance = distanceBetweenRooms;
    116.                             possibleConnectionFound = true;
    117.                             bestTileA = tileA;
    118.                             bestTileB = tileB;
    119.                             bestRoomA = roomA;
    120.                             bestRoomB = roomB;
    121.                         }
    122.                     }
    123.                 }
    124.             }
    125.  
    126.             if (possibleConnectionFound) {
    127.                 CreatePassage(bestRoomA, bestRoomB, bestTileA, bestTileB);
    128.             }
    129.         }
    130.     }
    131.  
    132.     void CreatePassage(Room roomA, Room roomB, Coord tileA, Coord tileB) {
    133.         Room.ConnectRooms (roomA, roomB);
    134.         Debug.DrawLine (CoordToWorldPoint (tileA), CoordToWorldPoint (tileB), Color.green, 100);
    135.     }
    136.  
    137.     Vector3 CoordToWorldPoint(Coord tile) {
    138.         return new Vector3 (-width / 2 + .5f + tile.tileX, 2, -height / 2 + .5f + tile.tileY);
    139.     }
    140.  
    141.     List<List<Coord>> GetRegions(int tileType) {
    142.         List<List<Coord>> regions = new List<List<Coord>> ();
    143.         int[,] mapFlags = new int[width,height];
    144.  
    145.         for (int x = 0; x < width; x ++) {
    146.             for (int y = 0; y < height; y ++) {
    147.                 if (mapFlags[x,y] == 0 && map[x,y] == tileType) {
    148.                     List<Coord> newRegion = GetRegionTiles(x,y);
    149.                     regions.Add(newRegion);
    150.  
    151.                     foreach (Coord tile in newRegion) {
    152.                         mapFlags[tile.tileX, tile.tileY] = 1;
    153.                     }
    154.                 }
    155.             }
    156.         }
    157.  
    158.         return regions;
    159.     }
    160.  
    161.     List<Coord> GetRegionTiles(int startX, int startY) {
    162.         List<Coord> tiles = new List<Coord> ();
    163.         int[,] mapFlags = new int[width,height];
    164.         int tileType = map [startX, startY];
    165.  
    166.         Queue<Coord> queue = new Queue<Coord> ();
    167.         queue.Enqueue (new Coord (startX, startY));
    168.         mapFlags [startX, startY] = 1;
    169.  
    170.         while (queue.Count > 0) {
    171.             Coord tile = queue.Dequeue();
    172.             tiles.Add(tile);
    173.  
    174.             for (int x = tile.tileX - 1; x <= tile.tileX + 1; x++) {
    175.                 for (int y = tile.tileY - 1; y <= tile.tileY + 1; y++) {
    176.                     if (IsInMapRange(x,y) && (y == tile.tileY || x == tile.tileX)) {
    177.                         if (mapFlags[x,y] == 0 && map[x,y] == tileType) {
    178.                             mapFlags[x,y] = 1;
    179.                             queue.Enqueue(new Coord(x,y));
    180.                         }
    181.                     }
    182.                 }
    183.             }
    184.         }
    185.  
    186.         return tiles;
    187.     }
    188.  
    189.     bool IsInMapRange(int x, int y) {
    190.         return x >= 0 && x < width && y >= 0 && y < height;
    191.     }
    192.  
    193.  
    194.     void RandomFillMap() {
    195.         if (useRandomSeed) {
    196.             seed = Time.time.ToString();
    197.         }
    198.  
    199.         System.Random pseudoRandom = new System.Random(seed.GetHashCode());
    200.  
    201.         for (int x = 0; x < width; x ++) {
    202.             for (int y = 0; y < height; y ++) {
    203.                 if (x == 0 || x == width-1 || y == 0 || y == height -1) {
    204.                     map[x,y] = 1;
    205.                 }
    206.                 else {
    207.                     map[x,y] = (pseudoRandom.Next(0,100) < randomFillPercent)? 1: 0;
    208.                 }
    209.             }
    210.         }
    211.     }
    212.  
    213.     void SmoothMap() {
    214.         for (int x = 0; x < width; x ++) {
    215.             for (int y = 0; y < height; y ++) {
    216.                 int neighbourWallTiles = GetSurroundingWallCount(x,y);
    217.  
    218.                 if (neighbourWallTiles > 4)
    219.                     map[x,y] = 1;
    220.                 else if (neighbourWallTiles < 4)
    221.                     map[x,y] = 0;
    222.  
    223.             }
    224.         }
    225.     }
    226.  
    227.     int GetSurroundingWallCount(int gridX, int gridY) {
    228.         int wallCount = 0;
    229.         for (int neighbourX = gridX - 1; neighbourX <= gridX + 1; neighbourX ++) {
    230.             for (int neighbourY = gridY - 1; neighbourY <= gridY + 1; neighbourY ++) {
    231.                 if (IsInMapRange(neighbourX,neighbourY)) {
    232.                     if (neighbourX != gridX || neighbourY != gridY) {
    233.                         wallCount += map[neighbourX,neighbourY];
    234.                     }
    235.                 }
    236.                 else {
    237.                     wallCount ++;
    238.                 }
    239.             }
    240.         }
    241.  
    242.         return wallCount;
    243.     }
    244.  
    245.     struct Coord {
    246.         public int tileX;
    247.         public int tileY;
    248.  
    249.         public Coord(int x, int y) {
    250.             tileX = x;
    251.             tileY = y;
    252.         }
    253.     }
    254.  
    255.  
    256.     class Room {
    257.         public List<Coord> tiles;
    258.         public List<Coord> edgeTiles;
    259.         public List<Room> connectedRooms;
    260.         public int roomSize;
    261.  
    262.         public Room() {
    263.         }
    264.  
    265.         public Room(List<Coord> roomTiles, int[,] map) {
    266.             tiles = roomTiles;
    267.             roomSize = tiles.Count;
    268.             connectedRooms = new List<Room>();
    269.  
    270.             edgeTiles = new List<Coord>();
    271.             foreach (Coord tile in tiles) {
    272.                 for (int x = tile.tileX-1; x <= tile.tileX+1; x++) {
    273.                     for (int y = tile.tileY-1; y <= tile.tileY+1; y++) {
    274.                         if (x == tile.tileX || y == tile.tileY) {
    275.                             if (map[x,y] == 1) {
    276.                                 edgeTiles.Add(tile);
    277.                             }
    278.                         }
    279.                     }
    280.                 }
    281.             }
    282.         }
    283.  
    284.         public static void ConnectRooms(Room roomA, Room roomB) {
    285.             roomA.connectedRooms.Add (roomB);
    286.             roomB.connectedRooms.Add (roomA);
    287.         }
    288.  
    289.         public bool IsConnected(Room otherRoom) {
    290.             return connectedRooms.Contains(otherRoom);
    291.         }
    292.     }
    293. }
    My Code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class MapGenerator : MonoBehaviour
    6. {
    7.     public int width;
    8.     public int height;
    9.     public int wall;
    10.     public int room;
    11.  
    12.     public string seed;
    13.     public bool useRandomSeed;
    14.     [Range(0, 100)]
    15.     public int randFillPercent;
    16.  
    17.     int[,] map;
    18.  
    19.     void Start()
    20.     {
    21.         GenerateMap();
    22.     }
    23.     void Update()
    24.     {
    25.         if (Input.GetMouseButtonDown(0))
    26.         {
    27.             GenerateMap();
    28.         }
    29.     }
    30.     void GenerateMap()
    31.     {
    32.         map = new int[width, height];
    33.         RandomFillMap();
    34.         for (int i = 0; i < 5; i++)
    35.         {
    36.             SmoothMap();
    37.         }
    38.  
    39.         ProcessMap ();
    40.  
    41.         int borderedSize = 1;
    42.         int[,] borderedMap = new int[width + borderedSize * 2, height + borderedSize * 2];
    43.         for (int x = 0; x < borderedMap.GetLength(0); x++)
    44.         {
    45.             for (int y = 0; y < borderedMap.GetLength(1); y++)
    46.             {
    47.                 if(x>=borderedSize && x<width+borderedSize && y>=borderedSize && y < height + borderedSize)
    48.                 {
    49.                     borderedMap[x, y] = map[x - borderedSize, y - borderedSize];
    50.                 }
    51.                 else
    52.                 {
    53.                     borderedMap[x, y] = 1;
    54.                 }
    55.             }
    56.         }
    57.         MeshGenerator meshGen = GetComponent<MeshGenerator>();
    58.         meshGen.GenerateMesh(borderedMap, 1);
    59.     }
    60.  
    61.     void ProcessMap(){
    62.         List<List<Coord>> wallRegions = GetRegions (1);
    63.         int wallThresoldSize = wall;
    64.  
    65.         foreach (List<Coord> wallRegion in wallRegions) {
    66.             if (wallRegion.Count < wallThresoldSize) {
    67.                 foreach (Coord tile in wallRegion) {
    68.                     map [tile.tileX, tile.tileY] = 0;
    69.                 }
    70.             }
    71.         }
    72.  
    73.         List<List<Coord>> roomRegions = GetRegions (0);
    74.         int roomThresoldSize = room;
    75.         List<Room> survivingRooms = new List<Room> ();
    76.  
    77.         foreach (List<Coord> roomRegion in roomRegions) {
    78.             if (roomRegion.Count < roomThresoldSize) {
    79.                 foreach (Coord tile in roomRegion) {
    80.                     map [tile.tileX, tile.tileY] = 1;
    81.                 }
    82.             } else {
    83.  
    84.                 survivingRooms.Add (new Room (roomRegion, map));
    85.             }
    86.  
    87.         }
    88.  
    89.         ConnectClosestRooms (survivingRooms);
    90.  
    91.     }
    92.  
    93.     void ConnectClosestRooms(List<Room> allRooms){
    94.  
    95.         int bestDistance = 0;
    96.         Coord bestTileA = new Coord ();
    97.         Coord bestTileB = new Coord ();
    98.         Room bestRoomA = new Room ();
    99.         Room bestRoomB = new Room ();
    100.         bool possibleConnectionFound = false;
    101.  
    102.         foreach (Room roomA in allRooms) {
    103.             possibleConnectionFound = false;
    104.             foreach (Room roomB in allRooms) {
    105.                 if (roomA == roomB) {
    106.                     continue;
    107.                 }
    108.                 if (roomA.IsConnected (roomB)) {
    109.                     possibleConnectionFound = false;
    110.                     break;
    111.                 }
    112.  
    113.                 for (int tileIndexA = 0; tileIndexA < roomA.edgeTiles.Count; tileIndexA++) {
    114.                     for (int tileIndexB = 0; tileIndexB < roomB.edgeTiles.Count; tileIndexB++) {
    115.  
    116.                         Coord tileA = roomA.edgeTiles [tileIndexA];
    117.                         Coord tileB = roomB.edgeTiles [tileIndexB];
    118.                         int distanceBetweenRooms = (int)(Mathf.Pow (tileA.tileX - tileB.tileX, 2) + Mathf.Pow (tileA.tileY - tileB.tileY, 2));
    119.  
    120.                         if (distanceBetweenRooms < bestDistance || !possibleConnectionFound) {
    121.                             bestDistance = distanceBetweenRooms;
    122.                             bestTileA = tileA;
    123.                             bestTileB = tileB;
    124.                             bestRoomA = roomA;
    125.                             bestRoomB = roomB;
    126.                             possibleConnectionFound = true;
    127.                         }
    128.                     }
    129.  
    130.                 }
    131.             }
    132.      
    133.         if (possibleConnectionFound) {
    134.             CreatePassage (bestRoomA, bestRoomB, bestTileA, bestTileB);
    135.         }
    136.     }
    137.  
    138.     }
    139.  
    140.     void CreatePassage(Room roomA, Room roomB, Coord tileA, Coord tileB){
    141.         Room.ConnectRooms (roomA, roomB);
    142.         Debug.DrawLine (CoordToWorldPoint(tileA), CoordToWorldPoint(tileB), Color.green, 100);
    143.  
    144.     }
    145.  
    146.     Vector3 CoordToWorldPoint(Coord tile){
    147.         return new Vector3 (-width / 2 + .5f + tile.tileX, 2, -height / 2 + .5f + tile.tileY);
    148.     }
    149.  
    150.     List<List<Coord>> GetRegions(int tileType){
    151.         List<List<Coord>> regions = new List<List<Coord>> ();
    152.         int[,] mapFlags = new int[width, height];
    153.  
    154.         for (int x = 0; x < width; x++) {
    155.             for (int y = 0; y < height; y++) {
    156.                 if (mapFlags [x, y] == 0 && map [x, y] == tileType) {
    157.                     List<Coord> newRegion = GetRegionTiles (x, y);
    158.                     regions.Add (newRegion);
    159.  
    160.                     foreach(Coord tile in newRegion){
    161.                         mapFlags [tile.tileX, tile.tileY] = 1;
    162.  
    163.                     }
    164.  
    165.  
    166.                 }
    167.  
    168.             }
    169.  
    170.         }
    171.         return regions;
    172.     }
    173.  
    174.  
    175.  
    176.     List<Coord> GetRegionTiles(int startX, int startY) {
    177.         List<Coord> tiles= new List<Coord>();
    178.         int[,] mapFlags = new int[width, height];
    179.         int tileType = map [startX, startY];
    180.  
    181.         Queue<Coord> queue = new Queue<Coord> ();
    182.         queue.Enqueue(new Coord(startX,startY));
    183.         mapFlags [startX, startY] = 1;
    184.  
    185.         while (queue.Count > 0) {
    186.             Coord tile = queue.Dequeue();
    187.             tiles.Add (tile);
    188.  
    189.             for (int x = tile.tileX-1; x <=tile.tileX+1; x++) {
    190.                 for (int y = tile.tileY-1; y <=tile.tileY+1; y++) {
    191.                     if (IsInMapRange (x, y) && (y == tile.tileY || x == tile.tileX)) {
    192.                         if (mapFlags [x, y] == 0 && map [x, y] == tileType) {
    193.                             mapFlags [x, y] = 1;
    194.                             queue.Enqueue (new Coord (x, y));
    195.  
    196.                         }
    197.  
    198.                     }
    199.  
    200.                 }
    201.             }
    202.         }
    203.         return tiles;
    204.     }
    205.  
    206.     bool IsInMapRange( int x, int y){
    207.  
    208.         return x >= 0 && x < width && y >= 0 && y < height;
    209.  
    210.     }
    211.  
    212.  
    213.  
    214.     void RandomFillMap()
    215.     {
    216.  
    217.         if (useRandomSeed) {
    218.             seed = Time.time.ToString ();
    219.         }
    220.  
    221.         Random.seed = seed.GetHashCode ();
    222.  
    223.         for (int x = 0; x < width; x++)
    224.         {
    225.             for (int y = 0; y < height; y++)
    226.             {
    227.                 if (x == 0 || x == width - 1 || y == 0 || y == height - 1)
    228.                 {
    229.                     map[x, y] = 1;
    230.  
    231.  
    232.                 }
    233.  
    234.  
    235.                 else {
    236.                     map[x, y] = (Random.Range(0, 100) < randFillPercent) ? 1 : 0;
    237.  
    238.                 }
    239.             }
    240.         }
    241.     }
    242.  
    243.     void SmoothMap()
    244.     {
    245.         for (int x = 0; x < width; x++)
    246.         {
    247.             for (int y = 0; y < height; y++)
    248.             {
    249.                 int neighborHoodTiles = GetSurrondingWallCount(x, y);
    250.  
    251.                 if (neighborHoodTiles > 4)
    252.                 {
    253.                     map[x, y] = 1;
    254.                 }
    255.                 else if (neighborHoodTiles < 4)
    256.                 {
    257.                     map[x, y] = 0;
    258.                 }
    259.             }
    260.         }
    261.     }
    262.  
    263.     int GetSurrondingWallCount(int gridX, int gridY)
    264.     {
    265.         int wallCount = 0;
    266.         for (int neighborX = gridX - 1; neighborX <= gridX + 1; neighborX++)
    267.         {
    268.             for (int neighborY = gridY - 1; neighborY <= gridY + 1; neighborY++)
    269.             {
    270.                 if (IsInMapRange(neighborX, neighborY) )
    271.                 {
    272.                     if (neighborX != gridX || neighborY != gridY)
    273.                     {
    274.                         wallCount += map[neighborX, neighborY];
    275.  
    276.                     }
    277.  
    278.                 }
    279.                 else
    280.                 {
    281.                     wallCount++;
    282.                 }
    283.             }
    284.         }
    285.         return wallCount;
    286.     }
    287.  
    288.     struct Coord{
    289.         public int tileX;
    290.         public int tileY;
    291.  
    292.         public Coord(int x, int y){
    293.             tileX=x;
    294.             tileY=y;
    295.  
    296.  
    297.         }
    298.  
    299.     }
    300.  
    301.     class Room{
    302.         public List<Coord> tiles;
    303.         public List<Coord> edgeTiles;
    304.         public List<Room> connectedRooms;
    305.         public int roomSize;
    306.  
    307.         public Room(){
    308.         }
    309.  
    310.         public Room(List<Coord> roomTiles, int[,] map){
    311.             tiles=roomTiles;
    312.             roomSize=tiles.Count;
    313.             connectedRooms=new List<Room>();
    314.  
    315.             edgeTiles=new List<Coord>();
    316.             foreach(Coord tile in tiles){
    317.                 for(int x=tile.tileX-1; x<=tile.tileX+1; x++){
    318.                     for(int y=tile.tileY-1;y<=tile.tileY+1; y++){
    319.                         if(x==tile.tileX||y==tile.tileY){
    320.                             if(map[x,y]==1){
    321.                                 edgeTiles.Add(tile);
    322.  
    323.                         }
    324.  
    325.                 }
    326.              
    327.                 }
    328.  
    329.             }
    330.  
    331.         }
    332.  
    333.  
    334.     }
    335.  
    336.  
    337.         public static void ConnectRooms(Room roomA, Room roomB){
    338.             roomA.connectedRooms.Add (roomB);
    339.             roomB.connectedRooms.Add (roomA);
    340.         }
    341.  
    342.         public bool IsConnected(Room otherRoom){
    343.  
    344.             return connectedRooms.Contains (otherRoom);
    345.  
    346.         }
    347.  
    348. }
    349. }
    350.  
    351.  
    Picture of what happened when I posted the code from the website into my code:
    upload_2016-6-11_20-49-24.png

    Another close up picture:
    upload_2016-6-11_20-50-11.png

    Picture of my own code:
    upload_2016-6-11_20-55-12.png

    Another picture of my own code with a random fill percentage of 55( last picture was 45 percent):
    :mad: For some weird reason, I can't post the picture here . srry but it showed a picture of two lines drawn in the middle of nowhere.
     
    Last edited: Jun 12, 2016
  34. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    This is th picture of my own code with a random fill percentage of 55%


    upload_2016-6-11_22-29-43.png
     

    Attached Files:

  35. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :eek: I am having a similar error too.
     
  36. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :mad: I'm on part 7 of the tutorial and I don't get how the surving rooms are ordered from greatest to least from ony using array.sort. Doesnt array.sort sort stuff from least to greatest or d oes it sort stuff from greatest to least?
     
  37. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    o_O Ok, I was coding along on part 7. However, when I wrote

    Code (CSharp):
    1. class Room : IComparable<Room> {
    they said IComparable was an error. Why is this. In my console, I received this message:

    Assets/MapGenerator.cs(301,22): error CS0246: The type or namespace name `IComparable`1' could not be found. Are you missing a using directive or an assembly reference?

    I looked at the websites code and saw that they used the namespace System and I didn't. The only reason why I did not use System was because I did not want an ambigous reference between the Random class since I am using UnityEngine.Random class rather than the other random class. Can I do this I Comparable thing without using System?
     
  38. greatness

    greatness

    Joined:
    Feb 20, 2016
    Posts:
    199
    :) So right now I just finished part 8 of the tutorial. The issues that are remaining is that I don't understand icomparable, CompareTo function, and the array list. sort method. Finally, the source code from the website is sadly not working :(.
     
  39. jeankepler

    jeankepler

    Joined:
    Jun 22, 2016
    Posts:
    1
    I have a very similar problem, I hit the play button and only have a blue background. Also, on Visual Studio that last paragraph seems to have problems with closing "}" when I copy paste or something. But then I tried to rewrite everything withouth having to copy paste anything inside and the same happened. And afterwards I tried to copy the code from the page and that one has the same problem, plus it's lacking the "return" command at the end. Could it be due to a new update in Unity? Mine's
    5.3.5F1 Personal

    Besides this little mishap, best tutorial ever. I gotta learn Procedural Generation. Best thing to be able to make a game that can be new for the creator itself....
     
  40. Saetheer

    Saetheer

    Joined:
    Jun 29, 2016
    Posts:
    1
    I'm having a issue with removing the mesh-walls from generation to generation. Can anyone please help me?



    this is my MeshGenerator.cs
    http://pastebin.com/0C4tyBrC <- .cs file to long, forum safety prevents me, thinks I'm a spambot.
     
    Last edited: Jun 29, 2016
  41. MehYam

    MehYam

    Joined:
    Jul 3, 2012
    Posts:
    1
    FYI, I have a fork of the project that should work with NavMesh. It adds some inspector buttons that allow you to create the map at design-time, save the meshes out so that you can make prefabs, etc. Here:

    https://github.com/MehYam/Procedural-Cave-Generation
     
  42. tarod-net

    tarod-net

    Joined:
    May 29, 2015
    Posts:
    8
    Same question here! Any ideas? Maybe getting all the Rooms and their Coordinates?
     
  43. Neopreno

    Neopreno

    Joined:
    Jan 8, 2016
    Posts:
    1
    Hello to all,

    first of all thanks a lot for the tutorial, it's very interesting, great job.

    I finished the tutorial and I added point lights inside the generated cave, but i don't know why the lights doesn't light as I expected. Seems that there angles that doesn't recive ilumination. The same thing happens to spot lights.

    Regards.
     

    Attached Files:

  44. Goodrum_

    Goodrum_

    Joined:
    Oct 8, 2016
    Posts:
    4
    I did the first tutorial and at the end when it came to generating a new map every time the mouse was clicked it didn't work. I even copied you're code into it directly and it still didn't work. Even with RandomSeed set to true, the same map is generated every time. Am I the only one with this issue?
     

    Attached Files:

  45. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    Hi Goodrum, try changing the code in the RandomFillMap method to:

    if (useRandomSeed){
    seed = UnityEngine.Random.Range(0,9999).ToString();
    }

    Let me know if that helps!
     
  46. Goodrum_

    Goodrum_

    Joined:
    Oct 8, 2016
    Posts:
    4
    Thanks Sebastian!

    This has make sit generate randomly on pressing the 'play' button, however clicking the mouse still doesn't generate a new map. Is this an important feature needed?
     
  47. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    No, it's not all that important.
     
  48. Goodrum_

    Goodrum_

    Joined:
    Oct 8, 2016
    Posts:
    4
    Now, after video 2, the cave seems to be generating on a different rotation and I cannot seem to figure out why. I have to look at it from the front view camera
     

    Attached Files:

  49. Cmushi

    Cmushi

    Joined:
    Jun 3, 2015
    Posts:
    1
    Hi Sebastian,

    I am using your tutorial to generate a pre-defined world map mesh by reading a bitmap to determine the map's dimensions and the province shapes . The bitmap image (example: http://imgur.com/i2O00Nb) represents the map which is made up of provinces where each province has a unique shape and RGB code. I tweaked the marching square algorithm to allow it to support more than 2 states (creating a multi color marching square) by storing the color of each pixel with the nodes and replacing the configuration switch with if else conditions of all the possible combinations (Each condition will generate the mesh triangles and store their colors). When I test the project, a purple mesh is generated and the following errors appear:

    • Mesh.colors is out of bounds. The supplied array needs to be the same size as the Mesh.vertices array.

    • UnityEngine.Mesh:set_colors(Color[])

    • MeshGenerator:GenerateMesh(Color[,], Single) (at Assets/MeshGenerator.cs:31)

    • MapGenerator:Start() (at Assets/MapGenerator.cs:13)
    I made a list of the array sizes when I debugged:
    • map (holds the RGB of each pixel of the bitmap): [23,12]
    • squares: [22,11]
    • meshColors: 296
    • meshVertices: 1758
    • meshTriangles: 331
    I have attached a copy of the scripts and bitmap. Could you take a look and tell me what I did wrong?

    Alternatively, is the marching square a feasible algorithm to generate to this type of mesh or would you recommend that I use a different one?

    Thanks in advance.

    Edit: I managed to get rid of the errors (moved variable color from 'ControlNode' to 'Node' and moved 'mesh.addColors' from the if statements to 'assignVertices') but the mesh generated is purple due to the lack of material. If I assign a material to the mesh, the colors get replaced by the color of the material. Does anyone know how to assign a material without replacing the colors of the mesh?
     

    Attached Files:

    Last edited: Oct 11, 2016
  50. AaronC5513

    AaronC5513

    Joined:
    Oct 31, 2015
    Posts:
    5
    You create a material that uses color as the albedo.