C#实现Astar 算法以及导航系统
生活随笔
收集整理的這篇文章主要介紹了
C#实现Astar 算法以及导航系统
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
C#實(shí)現(xiàn)Astar 算法以及導(dǎo)航系統(tǒng)
首先來(lái)說(shuō)一下 Astar 是什么,它是尋求兩個(gè)點(diǎn)之間一條最優(yōu)路徑 。但可能并不是最短路徑.
要找地圖上的一個(gè)點(diǎn)你就需要一個(gè)地圖,而且把地圖分成一個(gè)個(gè)格子,每個(gè)格子都有自己的信息
每個(gè)地圖格子身上的類
//格子類型 public enum E_Type_Node {//可行走區(qū)域walk,//不可走區(qū)域stop }//格子類 public class AstarNode {//格子坐標(biāo)public int x, y;public float f;//尋路消耗public float g;//起點(diǎn)距離消耗public float h;//終點(diǎn)距離消耗public AstarNode father;//父對(duì)象public E_Type_Node type;//格子類型public AstarNode(int x,int y,E_Type_Node type){this. x = x;this.y = y;this.type = type;} }AstarMgr
這里 實(shí)現(xiàn)了 A星 找到了路徑點(diǎn)
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Singletion<T> where T : class, new() {static T ins;public static T Ins{get{if (ins == null){ins = new T();}return ins;}} }// A星尋路管理器 public class AstarMgr : Singletion<AstarMgr> {//所有格子對(duì)象public AstarNode[,] nodes;//打開private List<AstarNode> OpenList=new List<AstarNode>();//關(guān)閉private List<AstarNode> CloseList= new List<AstarNode>();//地圖的 x,y 寬高private int Mapw;private int Maph;public void InitMapInfo(int w, int h){this.Mapw = w;this.Maph = h;//聲明容器 的長(zhǎng)度nodes = new AstarNode[w, h];AstarNode node;for (int i = 0; i < w; i++){for (int j = 0; j < h; j++){//只是為了測(cè)試node = new AstarNode(i, j, Random.Range(0, 100) < 20 ? E_Type_Node.stop : E_Type_Node.walk);nodes[i, j] = node;}}}/// <summary>/// 尋找路徑/// </summary>/// <param name="startPos">開始坐標(biāo)</param>/// <param name="endPos">結(jié)束坐標(biāo) </param>/// <returns></returns>public List<AstarNode> FindPath(Vector2 startPos, Vector2 endPos){//1.是否在地圖范圍內(nèi)if (startPos.x < 0 || startPos.x >= Mapw || startPos.y < 0 || startPos.y >= Maph || endPos.x < 0 || endPos.x >= Mapw || endPos.y < 0 || endPos.y >= Maph){Debug.Log("不在地圖范圍內(nèi)");return null;}AstarNode start = nodes[(int)startPos.x, (int)startPos.y];AstarNode end = nodes[(int)endPos.x, (int)endPos.y];//2.判斷格子是否阻擋if (start.type == E_Type_Node.stop || end.type == E_Type_Node.stop){Debug.Log("開始或結(jié)束點(diǎn)是阻擋");return null;}//清空上一次尋路數(shù)據(jù)// 清空關(guān)閉和尋路列表OpenList.Clear();CloseList.Clear();// 把開始點(diǎn)放入關(guān)閉列表中start.father = null;start.f = 0;start.g = 0;start.h = 0;CloseList.Add(start);while (true){//從起點(diǎn)開始找周圍的點(diǎn)并放入開啟列表中///左上x -1 y - 1FindNearNodeToOpenList(start.x - 1, start.y - 1, 1.4f, start, end);//上 x y-1FindNearNodeToOpenList(start.x, start.y - 1, 1, start, end);//右上 x+1,y-11FindNearNodeToOpenList(start.x + 1, start.y - 1, 1.4f, start, end);//左 x-1,yFindNearNodeToOpenList(start.x - 1, start.y, 1f, start, end);//右 x,y-1;FindNearNodeToOpenList(start.x + 1, start.y, 1f, start, end);//左下 x-1,y+1FindNearNodeToOpenList(start.x - 1, start.y + 1, 1.4f, start, end);//下 x,y+1FindNearNodeToOpenList(start.x, start.y + 1, 1, start, end);//右下 x+1,y+1FindNearNodeToOpenList(start.x + 1, start.y + 1, 1.4f, start, end);//死路判斷 開啟列表為空 就是死路if (OpenList.Count == 0){Debug.Log("死路");return null;}// 選擇 尋路消耗最小的點(diǎn)OpenList.Sort(SotrOpenList);//放入關(guān)閉列表中CloseList.Add(OpenList[0]);start = OpenList[0];OpenList.RemoveAt(0);if (start == end){//找到重點(diǎn)List<AstarNode> path = new List<AstarNode>();path.Add(end);while (end.father!=null){path.Add(end.father);end = end.father;}//反轉(zhuǎn)path.Reverse();return path;}}}private int SotrOpenList(AstarNode a, AstarNode b){if (a.f > b.f){return 1;}elsereturn -1; }/// <summary>/// 計(jì)算臨近點(diǎn) 是否可以放入Open List/// </summary>/// <param name="x"></param>/// <param name="y"></param>/// <param name="g"></param>/// <param name="father"></param>private void FindNearNodeToOpenList(int x, int y, float g, AstarNode father, AstarNode end){//判斷邊界if (x < 0 || x >= Mapw || y < 0 || y >= Maph){Debug.Log("不在地圖范圍內(nèi)");return;}//在范圍內(nèi) 取點(diǎn)AstarNode node = nodes[x, y];if (node == null || node.type == E_Type_Node.stop||CloseList.Contains(node)||OpenList.Contains(node)){return;}//計(jì)算尋路消耗//記錄父對(duì)象node.father = father;//計(jì)算g 我的開始距離= 我父親的距離 +我的距離node.g = father.g = g;node.h = Mathf.Abs(end.x - node.x) + Mathf.Abs(end.y - node.y);node.f = node.g + node.h;//通過了上面 的驗(yàn)證,存入開啟列表OpenList.Add(node);} }NavAgent( 導(dǎo)航實(shí)現(xiàn)類)
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events;public class NavAgent : MonoBehaviour {//速度private float speed;//路徑的集合private Vector3[] roads;// 回掉private UnityAction endFunc;//當(dāng)前路徑點(diǎn)下標(biāo)private int nextIndex = 0;private float totalTime;private float passedTime;private float vx, vy, vz;private bool isWalking;private Quaternion dstRot;public void Init() {}public void NavOnRoad(float speed, Vector3[] roads, UnityAction endFunc) {// step1: 準(zhǔn)備數(shù)據(jù),驗(yàn)證數(shù)據(jù)的合法性;this.speed = speed;this.roads = roads;this.endFunc = endFunc;if (this.roads.Length < 2) { return;}// step1: 將我們的角色放到起點(diǎn),調(diào)整好初始方向this.transform.position = this.roads[0];this.transform.LookAt(this.roads[1]);// end// step2: 下一個(gè)點(diǎn)數(shù)據(jù)相關(guān)this.nextIndex = 1;this.WalkToNext();// end}// 走向nextIndexprivate void WalkToNext(){if (this.nextIndex >= this.roads.Length) { // 走到了盡頭;this.isWalking = false;if (this.endFunc != null) {this.endFunc();}return;}// 從當(dāng)前點(diǎn)走到下一個(gè)點(diǎn)Vector3 src = this.transform.position;Vector3 dst = this.roads[this.nextIndex];Vector3 dir = dst - src;float len = dir.magnitude;if (len <= 0) {this.nextIndex++;this.WalkToNext();return;}this.totalTime = len / this.speed;this.passedTime = 0;// end// 分解速度this.vx = this.speed * dir.x / len;this.vy = this.speed * dir.y / len;this.vz = this.speed * dir.z / len;// end// 調(diào)整角色的朝向Quaternion old = this.transform.rotation;this.transform.LookAt(dst);this.dstRot = this.transform.rotation;this.transform.rotation = old;// endthis.isWalking = true;}public void StopNav() { }public void GoAheadOnRoad() { }private void Update() {if (this.isWalking == false) {return;}// 更新移動(dòng)的時(shí)間float dt = Time.deltaTime;this.passedTime += dt;if(this.passedTime > this.totalTime) {dt -= (this.passedTime - this.totalTime);}// end// 每次Update更新位置Vector3 pos = this.transform.position;pos.x += this.vx * dt;pos.y += this.vy * dt;pos.z += this.vz * dt;this.transform.position = pos;// 轉(zhuǎn)向插值this.transform.rotation = Quaternion.Slerp(this.transform.rotation, this.dstRot, 8.0f * dt);// endif (this.passedTime >= this.totalTime) {this.nextIndex++;this.WalkToNext();}} }總結(jié)
以上是生活随笔為你收集整理的C#实现Astar 算法以及导航系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用AStar算法解决八数码问题
- 下一篇: c语言除法连续运算,单片机C语言快速精度