새로운 일자리를 찾고 후, 바쁜 죽음은 블로그와 수리를 할 시간, 심지어는 드래곤 보트 축제 만두가 아닌, 같은 기사 소금에 절인 생선 (아마)와 함께 매일 일을 너무 피곤 깊이 자본주의 착취를 느낄 수 없습니다.
최근에 나는 아래 차원에서 ASTAR 길 찾기의 단결을 쓰기에 몰래.
tilemap의지도 untiy을 고수합니다.
아마 효과가 좋은 사진에 가지 않았다, 어떤 색상을 얻을 것이다, 그는 말했다 :
블랙 장애물, 녹색 경로 녹색, 시작과 사용의 끝은 좋은 게으른 O를 (╥﹏╥) O를 나타냅니다
원칙과 자세한 설명, 또는 큰 외국 신의 참조 :
https://www.redblobgames.com/pathfinding/a-star/introduction.html
해설은 다음과 같습니다 :
A * 알고리즘은 실제로 그리 디 알고리즘 및 너비 우선 탐색 알고리즘의 조합으로서 이해 될 수있다.
너비 우선 탐색 알고리즘, 각각의 최단 경로를 찾을 수 있습니다, 현재 위치의 시작점에 몇 가지 단계를 기록 할 모든 단계는 장점이 확실히 가장 짧은 경로를 찾을 수 있습니다, 더 큰 계산 단점의 양이지도는 매우 큰이 될 것입니다.
욕심쟁이 알고리즘, 현재 포인트 떨어진 그리드 가까운 끝에서, 장벽 상황이 없을 때마다 매우 효율적이지만, 장애물이있는 경우, 그것은 우회입니다.
A * 알고리즘은이 둘의 조합이며, 단계를 걸어 현재의 수와 끝점 현재 지점과 갈 수있는 근거로 그리드의 거리, 이점 장애물이있는 경우, 최단 거리를 찾는 것입니다없이 큰 폭 우선 검색의 양을 계산, 효율적이고 탐욕 알고리즘과 같은 장애물이 없을 때.
사실, 코드의 양이 내가 너무 게으른 해요, 많은 직접 밖으로 게시, 특별한 설명이없는 지금의 주석을 참조하지 않습니다.
사용은 System.Collections; 사용하여 System.Collections.Generic; 사용 UnityEngine, 사용 UnityEngine.Tilemaps; 공용 클래스 MapBehaviour : MonoBehaviour { 공공 Vector2Int mapsize; //지도 크기 tilemap TileMap 공공, 공공 타일 normalTile; // 흰색 타일 공공 타일 obstacleTile; // 검은 색 타일 공공 타일 pathTile; // 녹색 타일 공공의 INT의 obstacleCount; // 장애물의 수를 생성하는 공공 Vector3Int startPos을,위한 // 시작점 공공 Vector3Int의 endpos는; // 종료 개인 부울 hasStartPosSet을,위한 // 여부 출발점 개인 부울 hasEndPosSet; // 경우 설정 끝 개인 사전 <Vector3Int, INT> 검색 = 새로운 사전 <Vector3Int, INT> (); // 작업을 발견하는 수행 할 개인 사전 <Vector3Int, INT> 비용 = 새로운 사전 <Vector3Int, INT> (); // 소비의 현재 위치에 점을 시작 { 개인 사전 <Vector3Int, Vector3Int> pathSave = 새로운 사전 <Vector3Int, Vector3Int> (); // 되돌아 경로 저장 개인 목록 <Vector3Int> hadSearch = 새로운 목록 <Vector3Int> (); // 좌표 찾아왔다 개인 목록 <Vector3Int > 장애물 = 새로운 목록 <Vector3Int> (); // 장애물을 좌표 개인 무효 시작 () { CreateNormalTiles (); CreateObstacleTiles (); } 개인 무효 업데이트 () { IF (Input.GetMouseButtonDown (0)) { IF (! hasStartPosSet)는 제 클릭 기점 설정 // tilemap.SetTile (startPos, pathTile); startPos = tilemap.WorldToCell (Camera.main.ScreenToWorldPoint (Input.mousePosition)); { hasStartPosSet = TRUE; } 다른 경우 //第二次点击设置终点(hasEndPosSet!) { endpos는 = tilemap.WorldToCell (Camera.main.ScreenToWorldPoint (Input.mousePosition)); tilemap.SetTile (endpos는, pathTile); hasEndPosSet = TRUE; AStarSearchPath (); } 다른 //重置 { hasStartPosSet = 거짓; hasEndPosSet = 거짓; foreach는 (pathSave에서 VAR 항목) tilemap.SetTile (item.Key, normalTile); } search.Clear (); cost.Clear (); pathSave.Clear (); hadSearch.Clear (); } } } //创建白色地图 공개 무효 CreateNormalTiles () { INT (I = 0; I <mapSize.x; 내가 ++)에 대해 { 대 (INT의 J = 0; J <mapSize.y, J ++) { Vector3Int 위치 = 새로운 Vector3Int (I, J, 0); tilemap.SetTile (위치 normalTile); } } } //创建黑色障碍 공개 무효 CreateObstacleTiles () { 일람 <Vector3Int> = blankTiles 새로운 목록 <Vector3Int> (); 대해 INT (I = 0; I <mapSize.x; 내가 ++) { 대 (INT의 J = 0; J <mapSize.y, J ++) { blankTiles.Add (새 Vector3Int (I, J, 0)); } } 에 대해 INT (I = 0; I는 <obstacleCount; 내가 ++) { INT Random.Range 인덱스 = (0, blankTiles.Count); Vector3Int obstaclePos = blankTiles [인덱스]; blankTiles.RemoveAt (인덱스); obstacle.Add (obstaclePos); tilemap.SetTile (obstaclePos, obstacleTile); } } 算法ASTAR을 //查找 공공 무효 AStarSearchPath을 () { //初始化 search.Add합니다 (startPos, GetHeuristic합니다 (startPos, endpos는)); cost.Add합니다 (startPos, 0); hadSearch.Add합니다 (startPos) pathSave.Add합니다 (startPos 상기 startPos) 그동안 (search.Count> 0) { Vector3Int 전류 = GetShortestPos (); //의 최소 소비 작업 목록의 좌표를 얻을 IF (current.Equals (endpos는)) BREAK, 전류 (목록 <Vector3Int> = GetNeighbors 이웃) // 얻을 현재 좌표 이웃 의 foreach (다음 이웃의 VAR) { IF (! hadSearch.Contains (다음)) { cost.Add (다음, 선정 [현재] + 1); //는 격자의 소비 전류를 계산은 격자 실제로 플러스 단계 1 search.Add (다음, 비용 [다음] + GetHeuristic (다음, endpos는)); // 찾을 수있는 작업, 플러스 거리에 목적지에 의해 소비되는 전류의 소비 전류 값을 추가 pathSave.Add (다음, 전류) / / 경로를 저장 hadSearch.Add (다음); // 이미 조회 포인트를 추가 } } } (pathSave.ContainsKey (endpos는)) 경우 , ShowPath () 다른 사람의 인쇄 ( "아니오 도로"); } 주위에 사용할 수 가져 오기 // 이웃 개인 목록 <Vector3Int> GetNeighbors (Vector3Int 대상) { 목록 <Vector3Int> = 새로운 새로운 이웃 목록 <Vector3Int> (); Vector3Int 권리 = 목표 + Vector3Int.right; 타겟 = + Vector3Int.up을 Vector3Int; Vector3Int는 대상 = LEFT - Vector3Int.right 단계; = 목표를 Vector3Int - Vector3Int.up 단계; // 위 의 경우 (! 최대 up.y <mapSize.y && obstacle.Contains ()) { neighbors.Add (최대); } // 오른쪽 (! right.x <mapSize.x && obstacle.Contains (오른쪽))의 경우 { neighbors.Add (대상 + Vector3Int.right); } // 왼쪽 경우 (left.x> = 0 && obstacle.Contains (왼쪽)!) { neighbors.Add (대상 - Vector3Int.right); } // 아래로 경우 (down.y> = 0 &&! 다운 obstacle.Contains ()) { neighbors.Add (대상 - Vector3Int.up); } ; 이웃을 돌아 } 의 소비의 끝에 현재 위치 얻을 // 개인 INT GetHeuristic (Vector3Int POSA, Vector3Int을 POSB) { 반환 Mathf.Abs (posA.x - posB.x) + Mathf.Abs (posA.y - posB.y는); } 사전이 작업이 최소한의 소비 좌표 가져 오기 // ) (개인 Vector3Int의 GetShortestPos을 { KeyValuePair <Vector3Int을 , INT> = 최단 새로운 새 KeyValuePair <Vector3Int, INT> (Vector3Int.zero, Int.MaxValue) (상품 검색 VAR 단위)의 foreach { IF (item.Value <shortest.Value) { 최단 항목 =; } } search.Remove (shortest.Key); shortest.Key를 반환; } //显示查找完成的路径 개인 무효 ShowPath () { 인쇄 (pathSave.Count); Vector3Int 전류 = endpos는; 동안 (= 현재 startPos!) { Vector3Int 다음 pathSave = [현재]; tilemap.SetTile (전류 pathTile); = 다음 현재; } } }
사실, 어려움은 주로 각 다음 포인트의 계산을 고려하여 최소 포인트 값을 소비하는 사전이 이해하지 않으려면 각 포인트의 소비 값은 단계의 현재 수와 현재의 끝까지의 거리 출발점이다 합계 (전문 용어는 맨하탄 distance2333에서 맨하탄라고도 함).
끝.
복제, 교환에 오신 것을 환영합니다 소스를 나타냅니다!