MaximilianPs

TownGenerator

Jun 30th, 2021 (edited)
330
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 18.29 KB | None | 0 0
  1. /* =================================================================================================
  2.  *
  3.  *  How did it work?
  4.  *      - gridObject is an array (Vector3) that contains all Coordinates of each buildings and walls
  5.  *      - gridElement is an array (int) that contains all ID for each building.
  6.  *          in this way we can decide on which side the building should face based on the nearest element
  7.  *          also we can check where the road are, and if or not we already have spawned the Economic-Building (also called Commercial)
  8.  *
  9.  *  CITY ELEMENTS
  10.  *   0 = NONE  
  11.  *  99 = Main Square
  12.  *  82 = Wall Corner
  13.  *  81 = Wall
  14.  *  80 = Wall Gate!
  15.  *   1 = Building
  16.  *   2 = Decoration
  17.  *   3 = Duke Palace
  18.  *   4 = Barracks       // have to be placed near the gate and close to the road.
  19.  *  -1 = vertical straight road
  20.  *  -2 = horizontal straight road
  21.  *  -3 = bend road ?
  22.  *
  23.  *  Each cell HAVE TO BE 15x15 Unity's Unit!
  24.  *
  25.  * ============================================================================================= */
  26.  
  27. using System.Collections;
  28. using System.Collections.Generic;
  29. using UnityEngine;
  30. using UnityEditor;
  31.  
  32. public class TownGenerator : MonoBehaviour
  33. {
  34.     private Vector3[,] gridNodes;   // used to define the cells position
  35.     private int[,] gridElements;    // used to define all buildings
  36.  
  37.     [Range(5, 20)]
  38.     public int townSize = 5;
  39.     private int cellSize = 15;  // DO NOT TOUCH IT! // Change this parameter will mean change or check all prefabs involved!
  40.     [Space]
  41.     [SerializeField] private GameObject mainSquare;
  42.     [SerializeField] private GameObject xRoad;
  43.     [SerializeField] private GameObject zRoad;
  44.     [SerializeField] private GameObject bendRoad;
  45.  
  46.     [Space]
  47.     [Tooltip("Houses have to be the last on the bottom the list")]
  48.     [SerializeField] private GameObject[] commercialBuildings;
  49.     [SerializeField] private GameObject[] houseBuildings;
  50.     [Tooltip("0 = small town > higher value more big city")]
  51.     [SerializeField] private GameObject[] dukePalaces;
  52.     [SerializeField] private GameObject[] barracks;
  53.     [SerializeField] private GameObject[] decorations;
  54.     [SerializeField] private GameObject[] walls;
  55.     [SerializeField] private GameObject[] wallGate; // this is a 3 Cell size, so 15 x 3 = 45!
  56.     [SerializeField] private GameObject[] wallCorner;
  57.  
  58.     private GameObject gridObject;
  59.  
  60.     private int gridCenter = 0; // just 1 value 'cause the town is squared!
  61.     private void Start()
  62.     {
  63.         townSize += 2;
  64.  
  65.         // Init arrays
  66.         gridNodes = new Vector3[townSize, townSize];    // for the coords
  67.         gridElements = new int[townSize, townSize];     // for the buildings to be placed
  68.  
  69.         // Create the GameObject that will contain the entire town.
  70.         gridObject = new GameObject();
  71.         gridObject.name = "Grid Object";
  72.         gridObject.transform.parent = transform;
  73.  
  74.         // Create the GameObject that will contain the entire City Walls!
  75.         GameObject cityWalls = new GameObject();
  76.         cityWalls.name = "City Walls";
  77.         cityWalls.transform.parent = gridObject.transform;
  78.  
  79.         gridNodes = new Vector3[townSize, townSize];   // init the Grid            // This contain the building coordinates to spawn the building
  80.  
  81.         float halfCell = cellSize / 2;
  82.         gridCenter = Mathf.CeilToInt((float)townSize / 2) - 1;
  83.  
  84.         // First we fill the Coordinate for each cell.
  85.         for (int x = 0; x < townSize; x++)   // the grid construction goes from bottom-left on the top (along Z axis)
  86.         {
  87.             for (int z = 0; z < townSize; z++)
  88.             {
  89.                 gridNodes[x, z] = new Vector3((x * cellSize) + halfCell, 0f, (z * cellSize) + halfCell);    // Save the center of each cell.
  90.             }
  91.         }
  92.        
  93.         #region ===== PLACING WALLS AND GATES ===========================================
  94.         for (int x = 0; x < townSize; x++)   // the grid construction goes from bottom-left on the top (along Z axis)
  95.         {
  96.             for (int z = 0; z < townSize; z++)
  97.             {
  98.                 if (x == 0 || z == 0 || x == townSize - 1 || z == townSize - 1)
  99.                 {
  100.                     // Do I have to place the Gate?
  101.                     if (x == gridCenter)
  102.                     {
  103.                         if (z == 0) // We are at South
  104.                         {
  105.                             GameObject wall = Instantiate(wallGate[Random.Range(0, walls.Length - 1)], cityWalls.transform);
  106.                             wall.transform.position = gridNodes[x, z];
  107.                             wall.transform.rotation = Quaternion.Euler(0, 90, 0);
  108.                             wall.name = wall.name + ":" + x + "," + z;
  109.                             continue;
  110.                         }
  111.                         else
  112.                         {
  113.                             gridElements[x, z] = 80;
  114.  
  115.                             GameObject wall = Instantiate(wallGate[Random.Range(0, walls.Length - 1)], cityWalls.transform);
  116.                             wall.transform.SetPositionAndRotation(gridNodes[x, z], Quaternion.Euler(0, 270, 0));
  117.                             wall.name = wall.name + ":" + x + "," + z;
  118.  
  119.                             continue;
  120.                         }
  121.                     }
  122.                     else
  123.                     {
  124.                         gridElements[x, z] = 81;
  125.  
  126.                         WallBuilder(x, z, cityWalls.transform);
  127.                         continue;
  128.                     }
  129.                 }
  130.             }
  131.         }
  132.  
  133.         #endregion
  134.  
  135.         #region ===== PROTOTYPING THE TOWN ==============================================
  136.         bool isDucalPlaced = false;
  137.         bool barracksPlaced = false;
  138.  
  139.         for (int x = 0; x < townSize; x++)   // the grid construction goes from bottom-left on the top (along Z axis)
  140.         {
  141.             for (int z = 0; z < townSize; z++)
  142.             {
  143.                 if (gridElements[x, z] >= 80)   // This is used to avoid walls and gates cells ;-)
  144.                     continue;
  145.                
  146.                 #region === THIS IS FOR DEBUG ===
  147.                 // SpawnCube(x, z);
  148.                 // continue; // This is for the debug if you are using SpawnCube method
  149.                 #endregion ======================
  150.  
  151.                 // Main Square
  152.                 if (x == gridCenter && z == gridCenter)
  153.                 {
  154.                     gridElements[x, z] = 99;
  155.                     continue;
  156.                 }
  157.  
  158.                 // One Time Run for the Duke's Palace
  159.                 if (isDucalPlaced == false)
  160.                 {
  161.                     // Select one of the 8 spot for the Dual Building
  162.                     int ducalSpot = Random.Range(1, 8);
  163.                     //Debug.Log(ducalSpot);
  164.                     switch (ducalSpot)
  165.                     {
  166.                         case 1:
  167.                             isDucalPlaced = true;
  168.                             gridElements[gridCenter - 1, gridCenter - 1] = 3;   // Bottom Left
  169.  
  170.                             if (gridElements[gridCenter - 2, gridCenter - 1] == 0)
  171.                                 gridElements[gridCenter - 2, gridCenter - 1] = -2;   //... add road chunk
  172.  
  173.                             continue;
  174.                         case 2:
  175.                             isDucalPlaced = true;
  176.                             gridElements[gridCenter - 1, gridCenter] = 3;       // Mid Left
  177.  
  178.                             if (gridElements[gridCenter - 2, gridCenter] == 0)
  179.                                 gridElements[gridCenter - 2, gridCenter] = -2;   //... add road chunk
  180.  
  181.                             continue;
  182.                         case 3:
  183.                             isDucalPlaced = true;
  184.                             gridElements[gridCenter - 1, gridCenter + 1] = 3;   // Top Left
  185.  
  186.                             if (gridElements[gridCenter - 2, gridCenter + 1] == 0)
  187.                                 gridElements[gridCenter - 2, gridCenter + 1] = -2;   //... add road chunk
  188.  
  189.                             continue;
  190.                         case 4:
  191.                             isDucalPlaced = true;
  192.                             gridElements[gridCenter, gridCenter - 1] = 3;       // Bottom Mid.
  193.  
  194.                             continue;
  195.                         case 5:
  196.                             isDucalPlaced = true;
  197.                             gridElements[gridCenter, gridCenter + 1] = 3;       // Top Mid.
  198.  
  199.                             continue;
  200.                         case 6:
  201.                             isDucalPlaced = true;
  202.                             gridElements[gridCenter + 1, gridCenter - 1] = 3;    // Bottom Right
  203.  
  204.                             if (gridElements[gridCenter + 2, gridCenter - 1] == 0)
  205.                                 gridElements[gridCenter + 2, gridCenter - 1] = -2;   //... add road chunk
  206.  
  207.                             continue;
  208.                         case 7:
  209.                             isDucalPlaced = true;
  210.                             gridElements[gridCenter + 1, gridCenter] = 3;       // Mid Right
  211.  
  212.                             if (gridElements[gridCenter + 2, gridCenter] == 0)
  213.                                 gridElements[gridCenter + 2, gridCenter] = -2;   //... add road chunk
  214.  
  215.                             continue;
  216.                         case 8:
  217.                             isDucalPlaced = true;
  218.                             gridElements[gridCenter + 1, gridCenter + 1] = 3;   // Top Right
  219.  
  220.                             if (gridElements[gridCenter + 2, gridCenter + 1] == 0)
  221.                                 gridElements[gridCenter + 2, gridCenter + 1] = -2;   //... add road chunk
  222.  
  223.                             continue;
  224.                     }
  225.                 }
  226.  
  227.                 // Place the barracks
  228.                 if(barracksPlaced == false)
  229.                 {
  230.                     if (Utilities.RandomBool())
  231.                         gridElements[gridCenter - 1, 1] = 4;
  232.                     else
  233.                         gridElements[gridCenter + 1, townSize -2] = 4;
  234.                 }
  235.  
  236.  
  237.                 // Adding Roads
  238.                 if ((x == gridCenter && z > 0) || (x == gridCenter && z < townSize - 1))
  239.                 {
  240.                     if (gridElements[x, z] == 0)
  241.                         gridElements[x, z] = -1;
  242.  
  243.                     continue;
  244.                 }
  245.  
  246.                 // Nothing on the current cell, so let's place a building
  247.                     ///<TODO>Refine the block to choose better what spawn</TODO>
  248.                     if (gridElements[x, z] == 0)
  249.                     gridElements[x, z] = 1;
  250.                
  251.             }
  252.         }
  253.         #endregion
  254.  
  255.         SpawnBuildings();
  256.  
  257.         // Moving the Grid at 0,0,0
  258.         gridObject.transform.position = new Vector3(gridObject.transform.position.x - ((float)townSize * cellSize) / 2, 0f, gridObject.transform.position.z - ((float)townSize * cellSize) / 2);
  259.  
  260.     }
  261.  
  262.     private void SpawnBuildings()
  263.     {
  264.         #region ===== Objects Parents ===================================================
  265.         // Create the GameObject that will contain all Economic Buildings
  266.         GameObject roadsObjs = new GameObject();
  267.         roadsObjs.name = "Roads";
  268.         roadsObjs.transform.parent = gridObject.transform;
  269.  
  270.         // Create the GameObject that will contain all Economic Buildings
  271.         GameObject commBuilds = new GameObject();
  272.         commBuilds.name = "Buildings";
  273.         commBuilds.transform.parent = gridObject.transform;
  274.  
  275.         // Create the GameObject that will contain all city Decorations
  276.         GameObject decoObjs = new GameObject();
  277.         decoObjs.name = "Decorations";
  278.         decoObjs.transform.parent = gridObject.transform;
  279.         #endregion
  280.  
  281.         for (int x = 0; x < townSize; x++)   // the grid construction goes from bottom-left on the top (along Z axis)
  282.         {
  283.             for (int z = 0; z < townSize; z++)
  284.             {
  285.                 //Debug.Log("Spawning " + gridElements[x, z] + " at " + x + "," + z);
  286.  
  287.                 switch (gridElements[x,z])
  288.                 {
  289.                     case 0:
  290.                         break;
  291.                     case 99:
  292.                         GameObject square = Instantiate(mainSquare, gridObject.transform);
  293.                         square.transform.SetPositionAndRotation(gridNodes[x, z], Quaternion.Euler(0, 270, 0));
  294.                         square.name = square.name + ":" + x + "," + z;
  295.                         continue;
  296.                     case 82:
  297.                         continue;
  298.                     case 81:
  299.                         continue;
  300.                     case 80:
  301.                         continue;
  302.                     case 1:
  303.                         GameObject builds = Instantiate(commercialBuildings[Random.Range(0, commercialBuildings.Length)], commBuilds.transform);
  304.                         builds.transform.SetPositionAndRotation(gridNodes[x, z], Quaternion.Euler(0, 270, 0));
  305.                         builds.name = builds.name + ":" + x + "," + z;
  306.                         continue;
  307.                     case 2:
  308.                         continue;
  309.                     case 3:
  310.                         GameObject dukePalace = Instantiate(dukePalaces[0], commBuilds.transform);
  311.                         dukePalace.transform.SetPositionAndRotation(gridNodes[x, z], Quaternion.Euler(0, FaceMainSquare(x,z), 0));
  312.                         dukePalace.name = dukePalace.name + ":" + x + "," + z;
  313.                         break;
  314.                     case 4:
  315.                         GameObject barraksObj = Instantiate(barracks[0], commBuilds.transform);
  316.                         barraksObj.transform.SetPositionAndRotation(gridNodes[x, z], Quaternion.Euler(0, FaceMainSquare(x,z), 0));
  317.                         barraksObj.name = barraksObj.name + ":" + x + "," + z;
  318.                         break;
  319.                     case -1:        //  ROADS
  320.                         GameObject roadVert = Instantiate(zRoad, roadsObjs.transform);
  321.                         roadVert.transform.SetPositionAndRotation(gridNodes[x, z], Quaternion.Euler(0, 0, 0));
  322.                         roadVert.name = roadVert.name + ":" + x + "," + z;
  323.                         continue;
  324.                     case -2:
  325.                         GameObject roadHor = Instantiate(zRoad, roadsObjs.transform);
  326.                         roadHor.transform.SetPositionAndRotation(gridNodes[x, z], Quaternion.Euler(0, 90, 0));
  327.                         roadHor.name = roadHor.name + ":" + x + "," + z;
  328.                         continue;
  329.                     case -3:
  330.                         continue;
  331.                     default:
  332.                         continue;
  333.                 }
  334.             }
  335.         }
  336.     }
  337.  
  338.     private GameObject WallBuilder(int x, int z, Transform parent)
  339.     {
  340.        // Debug.Log(x + " " + z);
  341.  
  342.         GameObject wall;
  343.         float angle = 0f;
  344.  
  345.         bool corner = false;
  346.  
  347.         if (x == 0 && z == 0)                               // Bottom Left
  348.         {  
  349.             corner = true;
  350.             angle = 90;
  351.         }
  352.         else if (x == 0 && z == townSize - 1)               // Top Left
  353.         {
  354.             corner = true;
  355.             angle = 180;
  356.         }
  357.         else if (x == townSize - 1 && z == 0)               // Bottom Right
  358.         {
  359.             corner = true;
  360.             angle = 0;
  361.         }
  362.         else if (x == townSize - 1 && z == townSize - 1)    // Top Right
  363.         {
  364.             corner = true;
  365.             angle = 270;
  366.         }
  367.         else if (x == 0 && z > 0)                           // Walls Left
  368.         {
  369.             corner = false;
  370.             angle = 180;
  371.         }
  372.         else if (x == townSize -1 && z > townSize -1)       // Walls Right
  373.         {
  374.             corner = false;
  375.             angle = 180;
  376.         }
  377.         else if (x > 0 && z == townSize -1)                 // Walls North
  378.         {
  379.             corner = false;
  380.             angle = 270;
  381.         }
  382.         else if (x > 0 && z == 0)                           // Walls  South
  383.         {
  384.             corner = false;
  385.             angle = 90;
  386.         }
  387.  
  388.         // it's a corner
  389.         if (corner)
  390.         {
  391.             gridElements[x, z] = 82;
  392.  
  393.             wall = Instantiate(wallCorner[Random.Range(0, wallCorner.Length - 1)], parent);
  394.             wall.transform.position = gridNodes[x, z];
  395.             wall.transform.rotation = Quaternion.Euler(0, angle, 0);
  396.         }
  397.         else
  398.         {
  399.             gridElements[x, z] = 82;
  400.  
  401.             wall = Instantiate(walls[Random.Range(0, walls.Length - 1)], parent);
  402.             wall.transform.position = gridNodes[x, z];
  403.             wall.transform.rotation = Quaternion.Euler(0, angle, 0);
  404.             wall.name = wall.name + ":" + x +","+ z;
  405.         }
  406.  
  407.         return wall;
  408.     }
  409.  
  410.     /// <summary>
  411.     /// Rotate the building to face the MainSquare
  412.     /// </summary>
  413.     /// <param name="x">Your X grid position</param>
  414.     /// <param name="z">Your Z grid position</param>
  415.     /// <returns></returns>
  416.     private float FaceMainSquare(int x, int z)
  417.     {
  418.         if (x == gridCenter - 1 && z == gridCenter -1)  // Bottom Left
  419.             return 270;
  420.  
  421.         if (x == gridCenter - 1 && z == gridCenter)     // Mid Left
  422.             return 270;
  423.  
  424.         if (x == gridCenter - 1 && z == gridCenter +1)  // Top Left
  425.             return 270;
  426.  
  427.         if (x == gridCenter && z == gridCenter - 1)     // Bottom Center
  428.             return 0;
  429.  
  430.         if (x == gridCenter +1 && z == gridCenter + 1)  // Top Center
  431.             return 90;
  432.  
  433.         if (x == gridCenter + 1 && z == gridCenter - 1)  // Bottom Right
  434.             return 90;
  435.  
  436.         if (x == gridCenter + 1 && z == gridCenter)     // Mid Right
  437.             return 90;
  438.  
  439.         if (x == gridCenter + 1 && z == gridCenter + 1)  // Top Right
  440.             return 90;
  441.  
  442.         return 0;
  443.     }
  444.    
  445.     private void SpawnCube(int x, int z)
  446.     {
  447.         GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
  448.         cube.transform.localScale = new Vector3(cellSize, 2f, cellSize);
  449.         cube.transform.position = gridNodes[x, z];
  450.         cube.transform.position = new Vector3(cube.transform.position.x, cube.transform.position.y * .5f, cube.transform.position.z);
  451.         cube.transform.parent = gridObject.transform;
  452.         cube.transform.name = cube.name + " ("+ x + "," + z +")";
  453.     }
  454. }
  455.  
Add Comment
Please, Sign In to add comment