日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

C#实现Astar 算法以及导航系统

發布時間:2023/12/14 C# 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#实现Astar 算法以及导航系统 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C#實現Astar 算法以及導航系統

首先來說一下 Astar 是什么,它是尋求兩個點之間一條最優路徑 。但可能并不是最短路徑.
要找地圖上的一個點你就需要一個地圖,而且把地圖分成一個個格子,每個格子都有自己的信息

每個地圖格子身上的類

//格子類型 public enum E_Type_Node {//可行走區域walk,//不可走區域stop }//格子類 public class AstarNode {//格子坐標public int x, y;public float f;//尋路消耗public float g;//起點距離消耗public float h;//終點距離消耗public AstarNode father;//父對象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

這里 實現了 A星 找到了路徑點

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> {//所有格子對象public AstarNode[,] nodes;//打開private List<AstarNode> OpenList=new List<AstarNode>();//關閉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;//聲明容器 的長度nodes = new AstarNode[w, h];AstarNode node;for (int i = 0; i < w; i++){for (int j = 0; j < h; j++){//只是為了測試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">開始坐標</param>/// <param name="endPos">結束坐標 </param>/// <returns></returns>public List<AstarNode> FindPath(Vector2 startPos, Vector2 endPos){//1.是否在地圖范圍內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("不在地圖范圍內");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("開始或結束點是阻擋");return null;}//清空上一次尋路數據// 清空關閉和尋路列表OpenList.Clear();CloseList.Clear();// 把開始點放入關閉列表中start.father = null;start.f = 0;start.g = 0;start.h = 0;CloseList.Add(start);while (true){//從起點開始找周圍的點并放入開啟列表中///左上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;}// 選擇 尋路消耗最小的點OpenList.Sort(SotrOpenList);//放入關閉列表中CloseList.Add(OpenList[0]);start = OpenList[0];OpenList.RemoveAt(0);if (start == end){//找到重點List<AstarNode> path = new List<AstarNode>();path.Add(end);while (end.father!=null){path.Add(end.father);end = end.father;}//反轉path.Reverse();return path;}}}private int SotrOpenList(AstarNode a, AstarNode b){if (a.f > b.f){return 1;}elsereturn -1; }/// <summary>/// 計算臨近點 是否可以放入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("不在地圖范圍內");return;}//在范圍內 取點AstarNode node = nodes[x, y];if (node == null || node.type == E_Type_Node.stop||CloseList.Contains(node)||OpenList.Contains(node)){return;}//計算尋路消耗//記錄父對象node.father = father;//計算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;//通過了上面 的驗證,存入開啟列表OpenList.Add(node);} }

NavAgent( 導航實現類)

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;//當前路徑點下標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: 準備數據,驗證數據的合法性;this.speed = speed;this.roads = roads;this.endFunc = endFunc;if (this.roads.Length < 2) { return;}// step1: 將我們的角色放到起點,調整好初始方向this.transform.position = this.roads[0];this.transform.LookAt(this.roads[1]);// end// step2: 下一個點數據相關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;}// 從當前點走到下一個點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// 調整角色的朝向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;}// 更新移動的時間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;// 轉向插值this.transform.rotation = Quaternion.Slerp(this.transform.rotation, this.dstRot, 8.0f * dt);// endif (this.passedTime >= this.totalTime) {this.nextIndex++;this.WalkToNext();}} }

總結

以上是生活随笔為你收集整理的C#实现Astar 算法以及导航系统的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。