新しい仕事を探した後、忙しい瀕死、ブログをいじくり回すする時間は、深く資本主義の搾取を感じない、でもドラゴンボートフェスティバル餃子は、魚(おそらく)を塩漬け同じ記事で毎日仕事には余りにも疲れません。
つい最近、私は下の2DでのASTARの経路探索の団結を書くことに忍び込みます。
タイルマップの地図はuntiyに固執します。
おそらく効果は、いくつかの色を取得します、素敵な絵に行きませんでした、と彼は言いました:
ブラック、グリーン、パスのための緑、障害物を示し、使用の始めと終わりで、良い怠惰なO(╥﹏╥)O
原則と詳細な説明、またはビッグ外国の神の参照:
https://www.redblobgames.com/pathfinding/a-star/introduction.html
解説は次のとおりです。
*アルゴリズムは、実際に貪欲アルゴリズムと幅優先探索アルゴリズムの組み合わせとして理解することができます。
幅優先探索アルゴリズム、それぞれが最短経路を見つけることができ、すべてのステップは、現在のポイントの出発点にいくつかの手順を書き留めます、利点は間違いなく最短経路を見つけることができ、計算欠点より多くの量は、マップは非常に巨大になるだろうということです。
貪欲アルゴリズムは、現在の点離れグリッドに最も近い端部からの各時間は、障壁の状況が存在しない場合に非常に効率的であるが、障害物が存在する場合、それは迂回されます。
*アルゴリズムは両方の組み合わせで、現在のカウントのステップに行くための基礎として歩いて、エンドポイントへの現在のポイントとグリッドの距離、利点は最短距離を見つけるために、障害物がある場合ということで、無偉大な幅優先探索の量を算出し、効率的かつ貪欲法などに障害物が存在しない場合。
実際には、コードの量が大幅に直接出て掲載、具体的な説明は、今のコメントを参照してくださいがありません、私は怠け者です。
System.Collectionsは、使用して; System.Collections.Genericを使用して、 使用してUnityEngine; 使用UnityEngine.Tilemaps; パブリッククラスMapBehaviour:MonoBehaviour { 公共Vector2Int mapsize; //マップサイズの タイルマップタイルマップ公共、 公共のタイルnormalTile; //白いタイル 公共タイルobstacleTile。 //黒タイル パブリックタイルpathTile; //緑色タイル パブリックINT obstacleCount、生成される障害の//数 公共Vector3Int startPos; //のための開始点 公共Vector3Intのendposのを; //エンド プライベートブールhasStartPosSet;のため//か起点 プライベートBOOL hasEndPosSet; //終了するかどうか 民間辞典<Vector3Int、int型>検索 =新しい辞書<Vector3Int、整数>(); //は、 タスクが実行されるべき見つけます プライベート辞書<Vector3Int、int型>コスト =新しい辞書<Vector3Int、整数>(); // 消費の現在のポイントにポイントを始める { プライベート辞書<Vector3Int、Vector3Int> pathSave =新しい辞書<Vector3Int、Vector3Int>(); // バックトラックパス保存 プライベートリスト<Vector3Int> hadSearch =新しいリスト<Vector3Int>(); // 座標見つけなければならなかった 民間の一覧を<Vector3Int >障害物=新しいリスト<Vector3Int> (); // 障害物を調整し ます。private voidスタート() { 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 = FALSE; hasEndPosSet = falseは、 foreachの(pathSaveにおけるVARアイテム) { tilemap.SetTile(item.Key、normalTile)。 } search.Clear()。 cost.Clear()。 pathSave.Clear(); hadSearch.Clear(); } } } //创建白色地图 公共ボイドCreateNormalTiles() { (INT i = 0; I <mapSize.x; iは++)のために { ための(int型J = 0; J <mapSize.y; J ++) { Vector3Int位置=新しいですVector3Int(I、J、0); tilemap.SetTile(位置、normalTile)。 } } } //创建黑色障碍 ます。public void CreateObstacleTiles() { リスト<Vector3Int> blankTiles =新しいリスト<Vector3Int>(); のために(;; I <mapSize.x私は++ iの= 0 INT) { のために(int型J = 0; jの<mapSize.yあり、j ++) { blankTiles.Add(新しいVector3Int(I、J、0 )); } } のために(INT i = 0; iは<obstacleCount; iは++) { 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(NEXT) { cost.Add(次に、コスト[現在] + 1); //は格子の消費電流を計算するには、格子は、実際にはステッププラス1であります search.Add(次、コスト[次] + GetHeuristic(次、endposの)); // 検索するタスク、プラス距離ツー先で消費される電流の消費電流値を追加 pathSave.Add(次、現在の); / /パス保存 hadSearch.Add(次の); //すでに照会ポイント追加 } } } (pathSave.ContainsKey(endposの))のIF ShowPathを(); 他の 印刷( "ノーロード"); } //が周りの利用可能ゲット近所の プライベートリスト<Vector3Int> GetNeighbors(Vector3Intターゲット) { 一覧<Vector3Int> =新しい新しい隣人一覧<Vector3Int>(); Vector3Int右=ターゲット+ Vector3Int.right。 アップVector3Int =ターゲット+ Vector3Int.up。 Vector3Intは=ターゲット左- Vector3Int.rightを。 ダウンVector3Int =ターゲット- Vector3Int.up。 //アップ するif(!アップ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)。 } //ダウン IF(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、整数> =最短新しい新しいKeyValuePair <Vector3Int、整数>(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からマンハッタンと呼ばれる専門的用語)の合計。
終わり。
ソースを示す再現し、為替へようこそ!