29.Unity制作自动寻路逻辑的方法

29.Unity制作自动寻路逻辑的方法


29.1 题目

Unity中想要制作自动寻路逻辑,我们应该怎么做?(请至少说出两种做法)


29.2 深入解析

在Unity中,可以通过以下两种方法来实现自动寻路逻辑:

1. 使用Unity自带的网格寻路系统

Unity提供了一个强大的网格寻路系统,可以使用NavMesh来实现自动寻路。具体步骤如下:

  1. 创建NavMesh

    • 在场景中创建一个NavMeshSurface。
    • 在场景中选中需要进行寻路的地形或物体,标记为可行走区域。
    • 点击Bake生成NavMesh。
  2. 添加NavMeshAgent

    • 在需要进行自动寻路的角色上添加NavMeshAgent组件。
    • 设置目标位置,并通过NavMeshAgent组件的SetDestination方法来实现自动寻路。
using UnityEngine;
using UnityEngine.AI;

public class AutoNavigation : MonoBehaviour
{
    public Transform target; // 目标位置

    private NavMeshAgent agent;

    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        agent.SetDestination(target.position); // 设置目的地
    }

    void Update()
    {
        // 不断更新目的地,实现动态寻路
        if (target != null)
        {
            agent.SetDestination(target.position);
        }
    }
}

2. 自定义寻路算法(比如A星寻路算法)

A星(A*)算法是一种常用的图搜索算法,可以用来实现自定义的寻路逻辑。具体步骤如下:

  1. 定义节点类

    • 创建一个节点类来存储每个节点的信息,包括位置、父节点、G值(从起点到当前节点的代价)、H值(当前节点到终点的估算代价)和F值(G值和H值的总和)。
  2. 实现A星算法

    • 使用优先队列(或其他合适的数据结构)来存储打开列表(Open List)和关闭列表(Closed List)。
    • 在Open List中找到F值最小的节点,检查其邻居节点并进行相应更新。
    • 重复以上步骤,直到找到目标节点或Open List为空。
using System.Collections.Generic;
using UnityEngine;

public class AStarPathfinding : MonoBehaviour
{
    public Transform startPoint; // 起点
    public Transform endPoint; // 终点

    private List<Node> openList = new List<Node>();
    private List<Node> closedList = new List<Node>();

    // 节点类
    class Node
    {
        public Vector3 position; // 节点位置
        public Node parent; // 父节点
        public float g; // G值
        public float h; // H值
        public float f => g + h; // F值
    }

    void Start()
    {
        // 初始化起点和终点
        Node startNode = new Node { position = startPoint.position, g = 0, h = Vector3.Distance(startPoint.position, endPoint.position) };
        Node endNode = new Node { position = endPoint.position };

        openList.Add(startNode);

        // A星算法主循环
        while (openList.Count > 0)
        {
            Node currentNode = GetNodeWithLowestF();

            // 找到终点
            if (currentNode.position == endNode.position)
            {
                Debug.Log("路径找到!");
                return;
            }

            openList.Remove(currentNode);
            closedList.Add(currentNode);

            foreach (Node neighbor in GetNeighbors(currentNode))
            {
                if (closedList.Contains(neighbor))
                    continue;

                float tentativeG = currentNode.g + Vector3.Distance(currentNode.position, neighbor.position);

                if (!openList.Contains(neighbor))
                {
                    openList.Add(neighbor);
                }
                else if (tentativeG >= neighbor.g)
                {
                    continue;
                }

                neighbor.parent = currentNode;
                neighbor.g = tentativeG;
                neighbor.h = Vector3.Distance(neighbor.position, endNode.position);
            }
        }

        Debug.Log("没有找到路径!");
    }

    Node GetNodeWithLowestF()
    {
        Node lowestFNode = openList[0];
        foreach (Node node in openList)
        {
            if (node.f < lowestFNode.f)
                lowestFNode = node;
        }
        return lowestFNode;
    }

    List<Node> GetNeighbors(Node node)
    {
        List<Node> neighbors = new List<Node>();
        // 添加邻居节点的逻辑
        // ...
        return neighbors;
    }
}

总结

  1. Unity自带的网格寻路系统

    • 使用NavMesh进行路径规划和导航。
    • 简单易用,适合大多数场景。
  2. 自定义寻路算法(比如A星寻路算法)

    • 灵活可定制,可以根据具体需求实现复杂的路径规划逻辑。
    • 适合需要特殊路径规划策略的场景。

这两种方法各有优劣,可以根据具体的项目需求选择合适的寻路方案。


29.3 答题示例

“Unity 中做自动寻路,一种是 NavMesh:在场景中 Bake NavMesh,给角色挂 NavMeshAgent,通过 agent.SetDestination(target) 即可;
另一种是 自定义寻路(如 A* 算法):自己构建节点网格,维护 Open/Closed 列表,按 F = G + H 选取最优节点,最终生成路径并逐点移动。”


29.4 关键词联想

  • NavMeshSurface / NavMeshAgent
  • Bake NavMesh
  • SetDestination
  • A 算法*
  • Open List / Closed List
  • F = G + H
  • 节点网格
  • 路径重建


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏