Advertisement
Guest User

Astar From Unity Tilemaps

a guest
Nov 25th, 2017
3,054
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.32 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.Tilemaps;
  5. public class CreateNodesFromTilemaps : MonoBehaviour {
  6. //did some stuff to the actions in npc so they can get closer to the Nodes without the glitchyness
  7.  
  8. //changed execution order for this and world builder
  9. public Grid gridBase;
  10. public Tilemap floor;//floor of world
  11. public List<Tilemap> obstacleLayers; //all layers that contain objects to navigate around
  12. public GameObject nodePrefab;
  13.  
  14. //these are the bounds of where we are searching in the world for tiles, have to use world coords to check for tiles in the tile map
  15. public int scanStartX=-250,scanStartY=-250,scanFinishX=250,scanFinishY=250;
  16.  
  17.  
  18. public List<GameObject> unsortedNodes;//all the nodes in the world
  19. public GameObject[,] nodes; //sorted 2d array of nodes, may contain null entries if the map is of an odd shape e.g. gaps
  20. // Use this for initialization
  21. void Awake () {
  22. unsortedNodes = new List<GameObject> ();
  23. //Debug.Log ("Floor is size "+floor.size);
  24. //foreach (Tilemap t in obstacleLayers) {
  25. // Debug.Log ("Obstacle " + t.name + " Is size " + t.size);
  26. //}
  27.  
  28. }
  29.  
  30. public void generateNodes()
  31. {
  32.  
  33. createNodes ();
  34. //just call this and plug the resulting 2d array of nodes into your own A* algorithm
  35. }
  36.  
  37. // Update is called once per frame
  38. void Update () {
  39.  
  40. }
  41. public int gridBoundX = 0, gridBoundY = 0;
  42.  
  43. void createNodes()
  44. {
  45. int gridX = 0; //use these to work out the size and where each node should be in the 2d array we'll use to store our nodes so we can work out neighbours and get paths
  46. int gridY = 0;
  47.  
  48. bool foundTileOnLastPass = false;
  49.  
  50. //scan tiles and create nodes based on where they are
  51. for(int x = scanStartX;x<scanFinishX;x++)
  52. {
  53. for (int y = scanStartY; y < scanFinishY; y++) {
  54. //go through our world bounds in increments of 1
  55. TileBase tb = floor.GetTile (new Vector3Int (x, y, 0)); //check if we have a floor tile at that world coords
  56. if (tb == null) {
  57. } else {
  58. //if we do we go through the obstacle layers and check if there is also a tile at those coords if so we set founObstacle to true
  59. bool foundObstacle = false;
  60. foreach (Tilemap t in obstacleLayers) {
  61. TileBase tb2 = t.GetTile (new Vector3Int (x, y, 0));
  62.  
  63. if (tb2 == null) {
  64.  
  65. } else {
  66. foundObstacle = true;
  67. }
  68.  
  69. //if we want to add an unwalkable edge round our unwalkable nodes then we use this to get the neighbours and make them unwalkable
  70. if (unwalkableNodeBorder > 0) {
  71. List<TileBase> neighbours = getNeighbouringTiles (x, y, t);
  72. foreach(TileBase tl in neighbours)
  73. {
  74. if (tl == null) {
  75.  
  76. } else {
  77. foundObstacle = true;
  78. }
  79. }
  80. }
  81. }
  82.  
  83. if (foundObstacle == false) {
  84. //if we havent found an obstacle then we create a walkable node and assign its grid coords
  85. GameObject node = (GameObject)Instantiate (nodePrefab, new Vector3 (x + 0.5f + gridBase.transform.position.x, y + 0.5f+ gridBase.transform.position.y, 0), Quaternion.Euler (0, 0, 0));
  86. WorldTile wt = node.GetComponent<WorldTile> ();
  87. wt.gridX = gridX;
  88. wt.gridY = gridY;
  89. foundTileOnLastPass = true; //say that we have found a tile so we know to increment the index counters
  90. unsortedNodes.Add (node);
  91.  
  92. node.name = "NODE " + gridX.ToString () + " : " + gridY.ToString ();
  93.  
  94. } else {
  95. //if we have found an obstacle then we do the same but make the node unwalkable
  96. GameObject node = (GameObject)Instantiate (nodePrefab, new Vector3 (x + 0.5f+ gridBase.transform.position.x, y + 0.5f+ gridBase.transform.position.y, 0), Quaternion.Euler (0, 0, 0));
  97. //we add the gridBase position to ensure that the nodes are ontop of the tile they relate too
  98. node.GetComponent<SpriteRenderer> ().color = Color.red;
  99. WorldTile wt = node.GetComponent<WorldTile> ();
  100. wt.gridX = gridX;
  101. wt.gridY = gridY;
  102. wt.walkable = false;
  103. foundTileOnLastPass = true;
  104. unsortedNodes.Add (node);
  105. node.name = "UNWALKABLE NODE " + gridX.ToString () + " : " + gridY.ToString ();
  106.  
  107.  
  108. }
  109. gridY++; //increment the y counter
  110.  
  111.  
  112. if (gridX > gridBoundX) { //if the current gridX/gridY is higher than the existing then replace it with the new value
  113. gridBoundX = gridX;
  114. }
  115.  
  116. if (gridY > gridBoundY) {
  117. gridBoundY = gridY;
  118. }
  119. }
  120. }
  121. if (foundTileOnLastPass == true) {//since the grid is going from bottom to top on the Y axis on each iteration of the inside loop, if we have found tiles on this iteration we increment the gridX value and
  122. //reset the y value
  123. gridX++;
  124. gridY = 0;
  125. foundTileOnLastPass = false;
  126. }
  127. }
  128.  
  129. //put nodes into 2d array based on the
  130. nodes = new GameObject[gridBoundX+1,gridBoundY+1];//initialise the 2d array that will store our nodes in their position
  131. foreach (GameObject g in unsortedNodes) { //go through the unsorted list of nodes and put them into the 2d array in the correct position
  132. WorldTile wt = g.GetComponent<WorldTile> ();
  133. //Debug.Log (wt.gridX + " " + wt.gridY);
  134. nodes [wt.gridX, wt.gridY] = g;
  135. }
  136.  
  137. //assign neighbours to nodes
  138. for (int x = 0; x < gridBoundX; x++) { //go through the 2d array and assign the neighbours of each node
  139. for (int y = 0; y < gridBoundY; y++) {
  140. if (nodes [x, y] == null) { //check if the coords in the array contain a node
  141.  
  142. }
  143. else{
  144. WorldTile wt = nodes [x, y].GetComponent<WorldTile> (); //if they do then assign the neighbours
  145. //if (wt.walkable == true) {
  146. wt.myNeighbours = getNeighbours (x, y, gridBoundX, gridBoundY);
  147. //}
  148. }
  149. }
  150. }
  151.  
  152. //after this we have our grid of nodes ready to be used by the astar algorigthm
  153.  
  154. }
  155.  
  156.  
  157. //gets neighbours of a tile at x/y in a specific tilemap, can also have a border
  158. public int unwalkableNodeBorder = 1;
  159. public List<TileBase> getNeighbouringTiles(int x,int y,Tilemap t)
  160. {
  161. List<TileBase> retVal = new List<TileBase>();
  162.  
  163. for (int i = x - unwalkableNodeBorder; i < x + unwalkableNodeBorder; i++) {
  164. for (int j = y - unwalkableNodeBorder; j < y + unwalkableNodeBorder; j++) {
  165. TileBase tile = t.GetTile(new Vector3Int(i,j,0));
  166. if (tile == null) {
  167.  
  168. } else {
  169. retVal.Add (tile);
  170. }
  171. }
  172. }
  173.  
  174. return retVal;
  175. }
  176.  
  177. //gets the neighbours of the coords passed in
  178. public List<WorldTile> getNeighbours(int x, int y,int width,int height)
  179. {
  180.  
  181. List<WorldTile> myNeighbours = new List<WorldTile> ();
  182.  
  183. //needs the width & height to work out if a tile is not on the edge, also needs to check if the nodes is null due to the accounting for odd shapes
  184.  
  185.  
  186. if (x > 0 && x < width-1) {
  187. //can get tiles on both left and right of the tile
  188.  
  189. if (y > 0 && y < height - 1) {
  190. //top and bottom
  191. if (nodes [x + 1, y] == null) {
  192.  
  193. } else {
  194.  
  195. WorldTile wt1 = nodes [x + 1, y].GetComponent<WorldTile> ();
  196. if (wt1 == null) {
  197. } else {
  198. myNeighbours.Add (wt1);
  199. }
  200. }
  201.  
  202. if (nodes [x - 1, y] == null) {
  203.  
  204. } else {
  205. WorldTile wt2 = nodes [x - 1, y].GetComponent<WorldTile> ();
  206.  
  207. if (wt2 == null) {
  208.  
  209. } else {
  210. myNeighbours.Add (wt2);
  211.  
  212. }
  213. }
  214.  
  215. if (nodes [x, y + 1] == null) {
  216.  
  217. } else {
  218. WorldTile wt3 = nodes [x, y + 1].GetComponent<WorldTile> ();
  219. if (wt3 == null) {
  220.  
  221. } else {
  222. myNeighbours.Add (wt3);
  223.  
  224. }
  225. }
  226.  
  227. if (nodes [x, y - 1] == null) {
  228.  
  229. } else {
  230.  
  231. WorldTile wt4 = nodes [x, y - 1].GetComponent<WorldTile> ();
  232. if (wt4 == null) {
  233.  
  234. } else {
  235. myNeighbours.Add (wt4);
  236. }
  237. }
  238.  
  239. } else if (y == 0) {
  240. //just top
  241. if (nodes [x + 1, y] == null) {
  242.  
  243. } else {
  244.  
  245. WorldTile wt1 = nodes [x + 1, y].GetComponent<WorldTile> ();
  246. if (wt1 == null) {
  247. } else {
  248. myNeighbours.Add (wt1);
  249. }
  250. }
  251.  
  252. if (nodes [x - 1, y] == null) {
  253.  
  254. } else {
  255. WorldTile wt2 = nodes [x - 1, y].GetComponent<WorldTile> ();
  256.  
  257. if (wt2 == null) {
  258.  
  259. } else {
  260. myNeighbours.Add (wt2);
  261.  
  262. }
  263. }
  264. if (nodes [x, y + 1] == null) {
  265.  
  266. } else {
  267. WorldTile wt3 = nodes [x, y + 1].GetComponent<WorldTile> ();
  268. if (wt3 == null) {
  269.  
  270. } else {
  271. myNeighbours.Add (wt3);
  272.  
  273. }
  274. }
  275. } else if (y == height - 1) {
  276. //just bottom
  277. if (nodes [x, y - 1] == null) {
  278.  
  279. } else {
  280.  
  281. WorldTile wt4 = nodes [x, y - 1].GetComponent<WorldTile> ();
  282. if (wt4 == null) {
  283.  
  284. } else {
  285. myNeighbours.Add (wt4);
  286. }
  287. }
  288. if (nodes [x + 1, y] == null) {
  289.  
  290. } else {
  291.  
  292. WorldTile wt1 = nodes [x + 1, y].GetComponent<WorldTile> ();
  293. if (wt1 == null) {
  294. } else {
  295. myNeighbours.Add (wt1);
  296. }
  297. }
  298.  
  299. if (nodes [x - 1, y] == null) {
  300.  
  301. } else {
  302. WorldTile wt2 = nodes [x - 1, y].GetComponent<WorldTile> ();
  303.  
  304. if (wt2 == null) {
  305.  
  306. } else {
  307. myNeighbours.Add (wt2);
  308.  
  309. }
  310. }
  311. }
  312.  
  313.  
  314. } else if (x == 0) {
  315. //can't get tile on left
  316. if (y > 0 && y < height - 1) {
  317. //top and bottom
  318.  
  319. if (nodes [x + 1, y] == null) {
  320.  
  321. } else {
  322.  
  323. WorldTile wt1 = nodes [x + 1, y].GetComponent<WorldTile> ();
  324. if (wt1 == null) {
  325. } else {
  326. myNeighbours.Add (wt1);
  327. }
  328. }
  329.  
  330. if (nodes [x, y - 1] == null) {
  331.  
  332. } else {
  333.  
  334. WorldTile wt4 = nodes [x, y - 1].GetComponent<WorldTile> ();
  335. if (wt4 == null) {
  336.  
  337. } else {
  338. myNeighbours.Add (wt4);
  339. }
  340. }
  341. if (nodes [x, y + 1] == null) {
  342.  
  343. } else {
  344. WorldTile wt3 = nodes [x, y + 1].GetComponent<WorldTile> ();
  345. if (wt3 == null) {
  346.  
  347. } else {
  348. myNeighbours.Add (wt3);
  349.  
  350. }
  351. }
  352. } else if (y == 0) {
  353. //just top
  354. if (nodes [x + 1, y] == null) {
  355.  
  356. } else {
  357.  
  358. WorldTile wt1 = nodes [x + 1, y].GetComponent<WorldTile> ();
  359. if (wt1 == null) {
  360. } else {
  361. myNeighbours.Add (wt1);
  362. }
  363. }
  364.  
  365. if (nodes [x, y + 1] == null) {
  366.  
  367. } else {
  368. WorldTile wt3 = nodes [x, y + 1].GetComponent<WorldTile> ();
  369. if (wt3 == null) {
  370.  
  371. } else {
  372. myNeighbours.Add (wt3);
  373.  
  374. }
  375. }
  376. } else if (y == height - 1) {
  377. //just bottom
  378. if (nodes [x + 1, y] == null) {
  379.  
  380. } else {
  381.  
  382. WorldTile wt1 = nodes [x + 1, y].GetComponent<WorldTile> ();
  383. if (wt1 == null) {
  384. } else {
  385. myNeighbours.Add (wt1);
  386. }
  387. }
  388. if (nodes [x, y - 1] == null) {
  389.  
  390. } else {
  391.  
  392. WorldTile wt4 = nodes [x, y - 1].GetComponent<WorldTile> ();
  393. if (wt4 == null) {
  394.  
  395. } else {
  396. myNeighbours.Add (wt4);
  397. }
  398. }
  399. }
  400. } else if (x == width-1) {
  401. //can't get tile on right
  402. if (y > 0 && y < height - 1) {
  403. //top and bottom
  404. if (nodes [x - 1, y] == null) {
  405.  
  406. } else {
  407. WorldTile wt2 = nodes [x - 1, y].GetComponent<WorldTile> ();
  408.  
  409. if (wt2 == null) {
  410.  
  411. } else {
  412. myNeighbours.Add (wt2);
  413.  
  414. }
  415. }
  416.  
  417. if (nodes [x, y + 1] == null) {
  418.  
  419. } else {
  420. WorldTile wt3 = nodes [x, y + 1].GetComponent<WorldTile> ();
  421. if (wt3 == null) {
  422.  
  423. } else {
  424. myNeighbours.Add (wt3);
  425.  
  426. }
  427. }
  428. if (nodes [x, y - 1] == null) {
  429.  
  430. } else {
  431.  
  432. WorldTile wt4 = nodes [x, y - 1].GetComponent<WorldTile> ();
  433. if (wt4 == null) {
  434.  
  435. } else {
  436. myNeighbours.Add (wt4);
  437. }
  438. }
  439. } else if (y == 0) {
  440. //just top
  441. if (nodes [x - 1, y] == null) {
  442.  
  443. } else {
  444. WorldTile wt2 = nodes [x - 1, y].GetComponent<WorldTile> ();
  445.  
  446. if (wt2 == null) {
  447.  
  448. } else {
  449. myNeighbours.Add (wt2);
  450.  
  451. }
  452. }
  453. if (nodes [x, y + 1] == null) {
  454.  
  455. } else {
  456. WorldTile wt3 = nodes [x, y + 1].GetComponent<WorldTile> ();
  457. if (wt3 == null) {
  458.  
  459. } else {
  460. myNeighbours.Add (wt3);
  461.  
  462. }
  463. }
  464. } else if (y == height - 1) {
  465. //just bottom
  466. if (nodes [x - 1, y] == null) {
  467.  
  468. } else {
  469. WorldTile wt2 = nodes [x - 1, y].GetComponent<WorldTile> ();
  470.  
  471. if (wt2 == null) {
  472.  
  473. } else {
  474. myNeighbours.Add (wt2);
  475.  
  476. }
  477. }
  478. if (nodes [x, y - 1] == null) {
  479.  
  480. } else {
  481.  
  482. WorldTile wt4 = nodes [x, y - 1].GetComponent<WorldTile> ();
  483. if (wt4 == null) {
  484.  
  485. } else {
  486. myNeighbours.Add (wt4);
  487. }
  488. }
  489. }
  490. }
  491.  
  492.  
  493. return myNeighbours;
  494. }
  495. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement