我是靠谱客的博主 隐形斑马,最近开发中收集的这篇文章主要介绍C#实现Astar 算法以及导航系统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 - 1
            FindNearNodeToOpenList(start.x - 1, start.y - 1, 1.4f, start, end);
            //上 x y-1
            FindNearNodeToOpenList(start.x, start.y - 1, 1, start, end);
            //右上 x+1,y-11
            FindNearNodeToOpenList(start.x + 1, start.y - 1, 1.4f, start, end);
            //左 x-1,y
            FindNearNodeToOpenList(start.x - 1, start.y, 1f, start, end);
            //右 x,y-1;
            FindNearNodeToOpenList(start.x + 1, start.y, 1f, start, end);
            //左下 x-1,y+1
            FindNearNodeToOpenList(start.x - 1, start.y + 1, 1.4f, start, end);
            //下 x,y+1
            FindNearNodeToOpenList(start.x, start.y + 1, 1, start, end);
            //右下 x+1,y+1
            FindNearNodeToOpenList(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;
        }
        else
         return -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
    }

    // 走向nextIndex
    private 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;
        // end

        this.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);
        // end

        if (this.passedTime >= this.totalTime) {
            this.nextIndex++;
            this.WalkToNext();
        }
    }
}

最后

以上就是隐形斑马为你收集整理的C#实现Astar 算法以及导航系统C#实现Astar 算法以及导航系统的全部内容,希望文章能够帮你解决C#实现Astar 算法以及导航系统C#实现Astar 算法以及导航系统所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部