You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何获取游戏对象与障碍物间NavMesh可达最近点Pn?

解决方案:获取NavMesh上靠近障碍物的可达目标点Pn

需求回顾

已知:

  • Pi:自身GameObject的transform.position
  • Po:障碍物的transform.position
  • Po周围存在半径为PoPn的NavMesh不可达区域,需要找到Pi与Po之间、靠近障碍物的NavMesh可达点Pn作为目标点

实现思路

通过定位不可达区域边界+NavMesh采样的组合方式实现:

  1. 计算Pi到Po的连线,找到该连线上距离Po恰好为不可达半径的点(不可达区域的边界点)
  2. 在该边界点附近的NavMesh上采样最近的可达点,即为Pn

代码实现

using UnityEngine;
using UnityEngine.AI;

public class NavMeshTargetHelper : MonoBehaviour
{
    [Header("障碍物设置")]
    public Transform obstacle;
    public float obstacleUnreachableRadius = 1.2f; // 障碍物周围不可达区域的半径

    /// <summary>
    /// 获取Pi与Po之间靠近障碍物的NavMesh可达点Pn
    /// </summary>
    /// <returns>Pn坐标</returns>
    public Vector3 GetPnPoint()
    {
        Vector3 piPos = transform.position;
        Vector3 poPos = obstacle.position;
        float distanceBetweenPiPo = Vector3.Distance(piPos, poPos);

        // 如果自身已经在不可达区域内,直接返回自身位置的NavMesh最近点
        if (distanceBetweenPiPo <= obstacleUnreachableRadius)
        {
            NavMeshHit hit;
            NavMesh.SamplePosition(piPos, out hit, obstacleUnreachableRadius * 2, NavMesh.AllAreas);
            return hit.position;
        }

        // 计算Pi-Po连线上,不可达区域的边界点
        Vector3 directionToPo = (poPos - piPos).normalized;
        Vector3 boundaryPoint = poPos - directionToPo * obstacleUnreachableRadius;

        // 在边界点附近采样NavMesh可达点
        NavMeshHit navHit;
        if (NavMesh.SamplePosition(boundaryPoint, out navHit, obstacleUnreachableRadius * 0.5f, NavMesh.AllAreas))
        {
            return navHit.position;
        }

        // 采样失败时,沿Pi方向逐步后退搜索最近可达点
        float searchStep = 0.1f;
        Vector3 searchPos = boundaryPoint;
        while (Vector3.Distance(searchPos, piPos) < distanceBetweenPiPo)
        {
            searchPos -= directionToPo * searchStep;
            if (NavMesh.SamplePosition(searchPos, out navHit, searchStep * 2, NavMesh.AllAreas))
            {
                return navHit.position;
            }
        }

        // 极端情况:返回Pi位置的NavMesh最近点
        NavMesh.SamplePosition(piPos, out navHit, obstacleUnreachableRadius, NavMesh.AllAreas);
        return navHit.position;
    }
}

关键细节说明

  • NavMesh.SamplePosition:Unity NavMesh核心采样函数,用于在指定范围内找到最近的NavMesh可达点,参数依次为采样原点、命中结果、采样半径、允许的NavMesh区域
  • 边界点计算:确保Pn尽可能靠近Pi-Po连线,符合“两点之间靠近障碍物”的需求
  • 容错处理:覆盖了自身在不可达区域内、边界点无NavMesh等极端情况,保证代码鲁棒性

内容的提问来源于stack exchange,提问作者Adam_WY_Jeong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 21:01:03