는 A * 길 찾기 알고리즘 2D를 사용하여 연합

새로운 일자리를 찾고 후, 바쁜 죽음은 블로그와 수리를 할 시간, 심지어는 드래곤 보트 축제 만두가 아닌, 같은 기사 소금에 절인 생선 (아마)와 함께 매일 일을 너무 피곤 깊이 자본주의 착취를 느낄 수 없습니다.

 

최근에 나는 아래 차원에서 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에서 맨하탄라고도 함).

 

끝.

 

복제, 교환에 오신 것을 환영합니다 소스를 나타냅니다!

 

추천

출처www.cnblogs.com/JinT-Hwang/p/11141202.html