前提・実現したいこと
ここを参考にして勉強している。
ランダムな迷路を生成したいが迷路の壁が削除されず迷路にならない。
発生している問題・エラーメッセージ
エラーメッセージは無し
該当のソースコード
c#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class CellScript : MonoBehaviour { 6 7 public GameObject wallL; 8 public GameObject wallR; 9 public GameObject wallU; 10 public GameObject wallD; 11} 12
c#
1 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5 6public class MazeGenerator : MonoBehaviour { 7 8 9 private void Start() 10 { 11 GenerateMaze(mazeRows, mazeColumns); 12 } 13 14 private void GenerateMaze(int rows, int columns) 15 { 16 if (mazeParent != null) DeleteMaze(); 17 18 mazeRows = rows; 19 mazeColumns = columns; 20 CreateLayout(); 21 } 22 23 // Creates the grid of cells. 24 public void CreateLayout() 25 { 26 InitValues(); 27 28 // Set starting point, set spawn point to start. 29 Vector2 startPos = new Vector2(-(cellSize * (mazeColumns / 2)) + (cellSize / 2), -(cellSize * (mazeRows / 2)) + (cellSize / 2)); 30 Vector2 spawnPos = startPos; 31 32 for (int x = 1; x <= mazeColumns; x++) 33 { 34 for (int y = 1; y <= mazeRows; y++) 35 { 36 GenerateCell(spawnPos, new Vector2(x, y)); 37 38 // Increase spawnPos y. 39 spawnPos.y += cellSize; 40 } 41 42 // Reset spawnPos y and increase spawnPos x. 43 spawnPos.y = startPos.y; 44 spawnPos.x += cellSize; 45 } 46 47 CreateCentre(); 48 RunAlgorithm(); 49 MakeExit(); 50 } 51 52 // This is where the fun stuff happens. 53 public void RunAlgorithm() 54 { 55 // Get start cell, make it visited (i.e. remove from unvisited list). 56 unvisited.Remove(currentCell); 57 58 // While we have unvisited cells. 59 while (unvisited.Count > 0) 60 { 61 List<Cell> unvisitedNeighbours = GetUnvisitedNeighbours(currentCell); 62 if (unvisitedNeighbours.Count > 0) 63 { 64 // Get a random unvisited neighbour. 65 checkCell = unvisitedNeighbours[Random.Range(0, unvisitedNeighbours.Count)]; 66 // Add current cell to stack. 67 stack.Add(currentCell); 68 // Compare and remove walls. 69 CompareWalls(currentCell, checkCell); 70 // Make currentCell the neighbour cell. 71 currentCell = checkCell; 72 // Mark new current cell as visited. 73 unvisited.Remove(currentCell); 74 } 75 else if (stack.Count > 0) 76 { 77 // Make current cell the most recently added Cell from the stack. 78 currentCell = stack[stack.Count - 1]; 79 // Remove it from stack. 80 stack.Remove(currentCell); 81 } 82 } 83 } 84 85 public void MakeExit() 86 { 87 // Create and populate list of all possible edge cells. 88 List<Cell> edgeCells = new List<Cell>(); 89 90 foreach (KeyValuePair<Vector2, Cell> cell in allCells) 91 { 92 if (cell.Key.x == 0 || cell.Key.x == mazeColumns || cell.Key.y == 0 || cell.Key.y == mazeRows) 93 { 94 edgeCells.Add(cell.Value); 95 } 96 } 97 98 // Get edge cell randomly from list. 99 Cell newCell = edgeCells[Random.Range(0, edgeCells.Count)]; 100 101 // Remove appropriate wall for chosen edge cell. 102 if (newCell.gridPos.x == 0) RemoveWall(newCell.cScript, 1); 103 else if (newCell.gridPos.x == mazeColumns) RemoveWall(newCell.cScript, 2); 104 else if (newCell.gridPos.y == mazeRows) RemoveWall(newCell.cScript, 3); 105 else RemoveWall(newCell.cScript, 4); 106 107 Debug.Log("Maze generation finished."); 108 } 109 110 public List<Cell> GetUnvisitedNeighbours(Cell curCell) 111 { 112 // Create a list to return. 113 List<Cell> neighbours = new List<Cell>(); 114 // Create a Cell object. 115 Cell nCell = curCell; 116 // Store current cell grid pos. 117 Vector2 cPos = curCell.gridPos; 118 119 foreach (Vector2 p in neighbourPositions) 120 { 121 // Find position of neighbour on grid, relative to current. 122 Vector2 nPos = cPos + p; 123 // If cell exists. 124 if (allCells.ContainsKey(nPos)) nCell = allCells[nPos]; 125 // If cell is unvisited. 126 if (unvisited.Contains(nCell)) neighbours.Add(nCell); 127 } 128 129 return neighbours; 130 } 131 132 // Compare neighbour with current and remove appropriate walls. 133 public void CompareWalls(Cell cCell, Cell nCell) 134 { 135 // If neighbour is left of current. 136 if (nCell.gridPos.x < cCell.gridPos.x) 137 { 138 RemoveWall(nCell.cScript, 2); 139 RemoveWall(cCell.cScript, 1); 140 } 141 // Else if neighbour is right of current. 142 else if (nCell.gridPos.x > cCell.gridPos.x) 143 { 144 RemoveWall(nCell.cScript, 1); 145 RemoveWall(cCell.cScript, 2); 146 } 147 // Else if neighbour is above current. 148 else if (nCell.gridPos.y > cCell.gridPos.y) 149 { 150 RemoveWall(nCell.cScript, 4); 151 RemoveWall(cCell.cScript, 3); 152 } 153 // Else if neighbour is below current. 154 else if (nCell.gridPos.y < cCell.gridPos.y) 155 { 156 RemoveWall(nCell.cScript, 3); 157 RemoveWall(cCell.cScript, 4); 158 } 159 } 160 161 // Function disables wall of your choosing, pass it the script attached to the desired cell 162 // and an 'ID', where the ID = the wall. 1 = left, 2 = right, 3 = up, 4 = down. 163 public void RemoveWall(CellScript cScript, int wallID) 164 { 165 if (wallID == 1) cScript.wallL.SetActive(false); 166 else if (wallID == 2) cScript.wallR.SetActive(false); 167 else if (wallID == 3) cScript.wallU.SetActive(false); 168 else if (wallID == 4) cScript.wallD.SetActive(false); 169 } 170 171 public void CreateCentre() 172 { 173 // Get the 4 centre cells using the rows and columns variables. 174 // Remove the required walls for each. 175 centreCells[0] = allCells[new Vector2((mazeColumns / 2), (mazeRows / 2) + 1)]; 176 RemoveWall(centreCells[0].cScript, 4); 177 RemoveWall(centreCells[0].cScript, 2); 178 centreCells[1] = allCells[new Vector2((mazeColumns / 2) + 1, (mazeRows / 2) + 1)]; 179 RemoveWall(centreCells[1].cScript, 4); 180 RemoveWall(centreCells[1].cScript, 1); 181 centreCells[2] = allCells[new Vector2((mazeColumns / 2), (mazeRows / 2))]; 182 RemoveWall(centreCells[2].cScript, 3); 183 RemoveWall(centreCells[2].cScript, 2); 184 centreCells[3] = allCells[new Vector2((mazeColumns / 2) + 1, (mazeRows / 2))]; 185 RemoveWall(centreCells[3].cScript, 3); 186 RemoveWall(centreCells[3].cScript, 1); 187 188 // Create a List of ints, using this, select one at random and remove it. 189 // We then use the remaining 3 ints to remove 3 of the centre cells from the 'unvisited' list. 190 // This ensures that one of the centre cells will connect to the maze but the other three won't. 191 // This way, the centre room will only have 1 entry / exit point. 192 List<int> rndList = new List<int> { 0, 1, 2, 3 }; 193 int startCell = rndList[Random.Range(0, rndList.Count)]; 194 rndList.Remove(startCell); 195 currentCell = centreCells[startCell]; 196 foreach(int c in rndList) 197 { 198 unvisited.Remove(centreCells[c]); 199 } 200 } 201 202 public void GenerateCell(Vector2 pos, Vector2 keyPos) 203 { 204 // Create new Cell object. 205 Cell newCell = new Cell(); 206 207 // Store reference to position in grid. 208 newCell.gridPos = keyPos; 209 // Set and instantiate cell GameObject. 210 newCell.cellObject = Instantiate(cellPrefab, pos, cellPrefab.transform.rotation); 211 // Child new cell to parent. 212 if (mazeParent != null) newCell.cellObject.transform.parent = mazeParent.transform; 213 // Set name of cellObject. 214 newCell.cellObject.name = "Cell - X:" + keyPos.x + " Y:" + keyPos.y; 215 // Get reference to attached CellScript. 216 newCell.cScript = newCell.cellObject.GetComponent<CellScript>(); 217 // Disable Cell sprite, if applicable. 218 if (disableCellSprite) newCell.cellObject.GetComponent<SpriteRenderer>().enabled = false; 219 220 // Add to Lists. 221 allCells[keyPos] = newCell; 222 unvisited.Add(newCell); 223 } 224 225 public void DeleteMaze() 226 { 227 if (mazeParent != null) Destroy(mazeParent); 228 } 229 230 public void InitValues() 231 { 232 // Check generation values to prevent generation failing. 233 if (IsOdd(mazeRows)) mazeRows--; 234 if (IsOdd(mazeColumns)) mazeColumns--; 235 236 if (mazeRows <= 3) mazeRows = 4; 237 if (mazeColumns <= 3) mazeColumns = 4; 238 239 // Determine size of cell using localScale. 240 cellSize = cellPrefab.transform.localScale.x; 241 242 // Create an empty parent object to hold the maze in the scene. 243 mazeParent = new GameObject(); 244 mazeParent.transform.position = Vector2.zero; 245 mazeParent.name = "Maze"; 246 } 247 248 public bool IsOdd(int value) 249 { 250 return value % 2 != 0; 251 } 252 253 public class Cell 254 { 255 public Vector2 gridPos; 256 public GameObject cellObject; 257 public CellScript cScript; 258 } 259} 260
試したこと
Google検索
補足情報(FW/ツールのバージョンなど)
unity 2018.2.10
このままでは「長すぎてここには載せられない」レベルのソースを一から書かないと回答できません。まずは、どのように実現しようとしているのかや、関連するソースコードの抜粋を記載してください。https://teratail.com/help/question-tipsも参考になると思います。
回答1件
あなたの回答
tips
プレビュー