Unity获取Agent导航网格上的随机点

核心原理是,获取导航网格上的一个网格三角形,然后获取这个网格三角形 上的随机点(对逐个两个顶点之间获取插值)

    /// <summary>
    /// 获取随机位置
    /// </summary>
    /// <returns></returns>
    public Vector3 GetRandomPoint()
    {
        NavMeshTriangulation navMeshData = NavMesh.CalculateTriangulation();

        int t = Random.Range(0, navMeshData.indices.Length - 3);

        Vector3 point = Vector3.Lerp(navMeshData.vertices[navMeshData.indices[t]], navMeshData.vertices[navMeshData.indices[t + 1]], Random.value);
        point = Vector3.Lerp(point, navMeshData.vertices[navMeshData.indices[t + 2]], Random.value);

        return point;
    }

    /// <summary>
    /// 获取一个高精度的范围外随机点
    /// </summary>
    /// <param name="targetPoint"></param>
    /// <param name="distance"></param>
    /// <param name="success"></param>
    /// <returns></returns>
    public Vector3 GetRandomRangePointWithHighPrecision(Vector3 targetPoint, float distance, out bool success)
    {
        NavMeshTriangulation navMeshData = NavMesh.CalculateTriangulation();
        List<int> list = new List<int>();
        //获取所有三角的第一个顶点的索引值
        for (int i = 0; i < navMeshData.indices.Length-3; i++)
            list.Add(i);
        int count = list.Count; Debug.Log("顶点数量:" + navMeshData.indices.Length);
        List<Vector3> triangle = new List<Vector3>();
        
        for (int i = 0; i < count; i++)
        {
            //判断当前的顶点是否在列表中,并且该顶点的另外两个顶点是否在列表中(如果不在,表示已经被判断过,并且不符合条件)
            int index = Random.Range(0, list.Count);
            if (Vector3.Distance(targetPoint, navMeshData.vertices[navMeshData.indices[list[index]]]) > distance) triangle.Add(navMeshData.vertices[navMeshData.indices[list[index]]]);
            if (list.Contains(list[index] + 1)&&Vector3.Distance(targetPoint, navMeshData.vertices[navMeshData.indices[list[index] + 1]]) > distance) triangle.Add(navMeshData.vertices[navMeshData.indices[list[index] + 1]]);
            if (list.Contains(list[index] + 2)&&Vector3.Distance(targetPoint, navMeshData.vertices[navMeshData.indices[list[index] + 2]]) > distance) triangle.Add(navMeshData.vertices[navMeshData.indices[list[index] + 2]]);
            if (triangle.Count > 0) break;
            list.RemoveAt(index);
        }

        Vector3 point = Vector3.zero;
        success = false;
        if (triangle.Count > 0)
        {
            point = GerLerpPoint(triangle);
            success = true;
        }
        return point;
    }

    /// <summary>
    /// 获取远离tartgetPoint的点
    /// </summary>
    /// <param name="tartpoint"></param>
    /// <returns></returns>
    public Vector3 GetRandomEscapPoint(Vector3 targetPoint,float distance,out bool success)
    {
        NavMeshTriangulation navMeshData = NavMesh.CalculateTriangulation();
        List<int> list = new List<int>();
        //获取所有三角的第一个顶点的索引值
        for(int i = 0; i < navMeshData.indices.Length; i+=3)
            list.Add(i);
        int count = list.Count;Debug.Log("顶点数量:"+navMeshData.indices.Length);
        List<Vector3> triangle=new List<Vector3>();
        for(int i = 0; i < count; i++)
        {
            int index = Random.Range(0, list.Count);
            if (Vector3.Distance(targetPoint, navMeshData.vertices[navMeshData.indices[list[index]]]) > distance) triangle.Add(navMeshData.vertices[navMeshData.indices[list[index]]]);
            if (Vector3.Distance(targetPoint, navMeshData.vertices[navMeshData.indices[list[index] + 1]]) > distance) triangle.Add(navMeshData.vertices[navMeshData.indices[list[index] + 1]]);
            if (Vector3.Distance(targetPoint, navMeshData.vertices[navMeshData.indices[list[index] + 2]]) > distance) triangle.Add(navMeshData.vertices[navMeshData.indices[list[index] + 2]]);
            if (triangle.Count > 0) break;
            list.RemoveAt(index);
        }

        Vector3 point = Vector3.zero;
        success = false;
        if (triangle.Count > 0)
        {
            point = GerLerpPoint(triangle);
            success = true;
        }
        return point;
    }
    //获取多个顶点之间的一个随机点
    Vector3 GerLerpPoint(List<Vector3> list)
    {
        Vector3 point = list[0];
        foreach(Vector3 v in list)
        {
            point = Vector3.Lerp(point, v, Random.value);
        }
        return point;
    }

 

posted @ 2020-05-09 01:06  小辉歌  阅读(1310)  评论(0编辑  收藏  举报