跳转至

Unity 6.3 — 导航 Module Reference

最后验证: 2026-02-13 Knowledge Gap: Unity 6 NavMesh 改进


概述

  • NavMesh:面向 AI 代理的内置寻路系统
  • NavMeshComponents:用于运行时 NavMesh 构建的包

烘焙导航网格

  1. 标记可行走表面:
  2. 选择 GameObject(地面/地形)
  3. Inspector > Navigation > Object 选项卡
  4. 勾选 “Navigation Static”

  5. 烘焙 NavMesh:

  6. Window > AI > Navigation
  7. Bake 选项卡
  8. 点击 “Bake”

  9. 配置设置:

  10. Agent Radius:代理的宽度(默认 0.5m)
  11. Agent Height:代理的高度(默认 2m)
  12. Max Slope:最大可行走坡度(默认 45°)
  13. Step Height:最大可攀爬台阶高度(默认 0.4m)

基础代理设置

using UnityEngine;
using UnityEngine.AI;

public class Enemy : MonoBehaviour {
    private NavMeshAgent agent;
    public Transform target;

    void Start() {
        agent = GetComponent<NavMeshAgent>();
    }

    void Update() {
        // ✅ Move to target
        agent.SetDestination(target.position);
    }
}

NavMeshAgent agent = GetComponent<NavMeshAgent>();

// Speed
agent.speed = 3.5f;

// Acceleration
agent.acceleration = 8f;

// Stopping distance
agent.stoppingDistance = 2f; // Stop 2m before destination

// Auto-braking (slow down at destination)
agent.autoBraking = true;

// Rotation speed
agent.angularSpeed = 120f; // Degrees per second

// Obstacle avoidance
agent.obstacleAvoidanceType = ObstacleAvoidanceType.HighQualityObstacleAvoidance;

检查路径状态

void Update() {
    agent.SetDestination(target.position);

    // Check if agent has a path
    if (agent.hasPath) {
        // Check if path is complete
        if (agent.pathStatus == NavMeshPathStatus.PathComplete) {
            Debug.Log("Valid path");
        } else if (agent.pathStatus == NavMeshPathStatus.PathPartial) {
            Debug.Log("Partial path (destination unreachable)");
        } else {
            Debug.Log("Invalid path");
        }
    }

    // Check if agent reached destination
    if (!agent.pathPending && agent.remainingDistance <= agent.stoppingDistance) {
        Debug.Log("Reached destination");
    }
}

计算路径(暂不移动)

NavMeshPath path = new NavMeshPath();
agent.CalculatePath(targetPosition, path);

if (path.status == NavMeshPathStatus.PathComplete) {
    // Valid path exists
    agent.SetPath(path); // Apply the path
}

定义区域

Window > AI > Navigation > Areas tab

  • Walkable:代价 1(默认)
  • Not Walkable:不可行走
  • Jump:代价 2(优先选择其他路线)
  • Custom:定义你自己的区域

分配区域代价

// Prefer shorter paths over low-cost paths
agent.areaMask = NavMesh.AllAreas; // Walk on all areas

// Only walk on "Walkable" area (avoid "Jump")
agent.areaMask = 1 << NavMesh.GetAreaFromName("Walkable");

// Add: GameObject > Add Component > NavMesh Obstacle

// Carve: Create hole in NavMesh (agents avoid)
// Don't Carve: Agent pushes through (local avoidance)

动态雕刻(移动障碍物)

NavMeshObstacle obstacle = GetComponent<NavMeshObstacle>();
obstacle.carving = true; // Create dynamic hole in NavMesh

  1. GameObject > Create Empty(在跳跃起点)
  2. 添加 Off Mesh Link 组件
  3. 设置 Start/End 变换
  4. 配置:
  5. Bi-Directional:可双向穿越
  6. Cost Override:此链接的路径代价
void Update() {
    // Check if agent is on an off-mesh link
    if (agent.isOnOffMeshLink) {
        // Manually traverse (e.g., play jump animation)
        StartCoroutine(TraverseOffMeshLink());
    }
}

IEnumerator TraverseOffMeshLink() {
    OffMeshLinkData data = agent.currentOffMeshLinkData;
    Vector3 startPos = agent.transform.position;
    Vector3 endPos = data.endPos;

    float duration = 0.5f;
    float elapsed = 0f;

    while (elapsed < duration) {
        agent.transform.position = Vector3.Lerp(startPos, endPos, elapsed / duration);
        elapsed += Time.deltaTime;
        yield return null;
    }

    agent.CompleteOffMeshLink(); // Resume normal pathfinding
}

安装

  1. Window > Package Manager
  2. 从 Git URL 添加:com.unity.ai.navigation

运行时 NavMesh 烘焙

using Unity.AI.Navigation;

public class NavMeshBuilder : MonoBehaviour {
    public NavMeshSurface surface;

    void Start() {
        // Bake NavMesh at runtime
        surface.BuildNavMesh();
    }

    void UpdateNavMesh() {
        // Update NavMesh after terrain changes
        surface.UpdateNavMesh(surface.navMeshData);
    }
}

Common Patterns

在路径点之间巡逻

public Transform[] waypoints;
private int currentWaypoint = 0;

void Update() {
    if (!agent.pathPending && agent.remainingDistance < 0.5f) {
        // Reached waypoint, move to next
        currentWaypoint = (currentWaypoint + 1) % waypoints.Length;
        agent.SetDestination(waypoints[currentWaypoint].position);
    }
}

追逐玩家

public Transform player;
public float chaseRange = 10f;

void Update() {
    float distance = Vector3.Distance(transform.position, player.position);

    if (distance <= chaseRange) {
        agent.SetDestination(player.position);
    } else {
        agent.ResetPath(); // Stop moving
    }
}

逃离玩家

public Transform player;
public float fleeRange = 5f;

void Update() {
    float distance = Vector3.Distance(transform.position, player.position);

    if (distance <= fleeRange) {
        // Run away from player
        Vector3 fleeDirection = transform.position - player.position;
        Vector3 fleeTarget = transform.position + fleeDirection.normalized * 10f;

        agent.SetDestination(fleeTarget);
    }
}

调试

  • Window > AI > Navigation > Bake tab
  • 勾选 "Show NavMesh" 以可视化可行走区域

代理路径 Gizmos

void OnDrawGizmos() {
    if (agent != null && agent.hasPath) {
        Gizmos.color = Color.green;
        Vector3[] corners = agent.path.corners;

        for (int i = 0; i < corners.Length - 1; i++) {
            Gizmos.DrawLine(corners[i], corners[i + 1]);
        }
    }
}

Performance Tips

  • 限制障碍物避让质量:对远处的代理使用 LowQualityObstacleAvoidance
  • 更新频率:如果目标未移动,不要每帧调用 SetDestination()
  • 区域掩码:限制可行走区域以缩小寻路搜索空间
  • NavMesh 分块:对于大型世界,使用分块 NavMesh(NavMeshComponents 包)

来源

  • https://docs.unity3d.com/6000.0/Documentation/Manual/Navigation.html
  • https://docs.unity3d.com/Packages/com.unity.ai.navigation@2.0/manual/index.html

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/Claude-Code-Game-Studios