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

Unity路径规划避障:两点间网格生成与光滑贝塞尔曲线构建问询

Solution for Unity Path & Grid Tasks

Alright, let's break down your two Unity challenges—obstacle-aware grid generation between random points, and smoothing your A* path with curves that stay collision-free while looking seamless.

1. Obstacle-Aware Grid Generation Between Random Points

First, you need a grid that connects your two random points but avoids obstacles. Here's a practical workflow:

  • Define your grid bounds: Calculate a rectangular region that encloses both random points, then expand it by a few grid units (e.g., 2-3x your cell size) to account for potential detours around obstacles. This prevents the grid from being too tight to find a valid path.
  • Mark obstacle cells: For each cell in your bounds, use Unity's Physics.OverlapBox or raycasting to check if the cell overlaps with colliders tagged as obstacles. Mark these cells as unwalkable in your grid data structure.
  • Validate path feasibility: Run your existing A* algorithm first to confirm there's a valid path between the two points. If no path exists, adjust your random points or expand the grid bounds until a path is found.
  • Optimize grid density (optional): Instead of generating a full grid across the entire bounds, generate cells only along and around the A* path. For example, take each path node and generate cells in a 3x3 (or larger) radius around it. This saves performance, especially in large scenes.

2. Smooth, Obstacle-Free Curves from A* Paths

Your current issue with jagged bezier curve transitions comes from not ensuring tangent continuity between segments, plus skipping collision checks. Here's how to fix this:

Step 1: Simplify the A* Path First

Redundant nodes in your A* path create unnecessary curve segments. Use the Ramer-Douglas-Peucker algorithm to prune nodes that don't significantly change the path direction—but add a collision check for each simplified segment:

List<Vector3> SimplifyPath(List<Vector3> originalPath, float epsilon)
{
    if (originalPath.Count <= 2) return originalPath;

    float maxDistance = 0;
    int index = 0;
    for (int i = 1; i < originalPath.Count - 1; i++)
    {
        float distance = DistancePointToLine(originalPath[i], originalPath[0], originalPath[^1]);
        if (distance > maxDistance)
        {
            maxDistance = distance;
            index = i;
        }
    }

    if (maxDistance > epsilon)
    {
        // Check if the simplified segment collides with obstacles
        if (!Physics.Linecast(originalPath[0], originalPath[^1], LayerMask.GetMask("Obstacles")))
        {
            var left = SimplifyPath(originalPath.GetRange(0, index + 1), epsilon);
            var right = SimplifyPath(originalPath.GetRange(index, originalPath.Count - index), epsilon);
            left.RemoveAt(left.Count - 1);
            left.AddRange(right);
            return left;
        }
    }

    return new List<Vector3> { originalPath[0], originalPath[^1] };
}

float DistancePointToLine(Vector3 point, Vector3 lineStart, Vector3 lineEnd)
{
    return Vector3.Cross(lineEnd - lineStart, point - lineStart).magnitude / (lineEnd - lineStart).magnitude;
}

Pro tip: Adjust epsilon based on your grid size—smaller values keep more nodes, larger values simplify more aggressively.

Step 2: Use Catmull-Rom Splines for Smooth Transitions

Catmull-Rom splines are perfect here because they automatically create smooth, continuous curves through your path nodes without manual control points. You can adjust the tension parameter to make curves tighter or looser:

List<Vector3> GenerateCatmullRomSpline(List<Vector3> pathNodes, int samplesPerSegment, float tension = 0.5f)
{
    List<Vector3> splinePoints = new List<Vector3>();
    if (pathNodes.Count < 2) return splinePoints;

    for (int i = 0; i < pathNodes.Count - 1; i++)
    {
        Vector3 p0 = i > 0 ? pathNodes[i - 1] : pathNodes[i];
        Vector3 p1 = pathNodes[i];
        Vector3 p2 = pathNodes[i + 1];
        Vector3 p3 = i < pathNodes.Count - 2 ? pathNodes[i + 2] : pathNodes[i + 1];

        for (float t = 0; t < 1; t += 1f / samplesPerSegment)
        {
            float t2 = t * t;
            float t3 = t2 * t;

            Vector3 point = 0.5f * (
                (2 * p1) +
                (-p0 + p2) * t +
                (2 * p0 - 5 * p1 + 4 * p2 - p3) * t2 +
                (-p0 + 3 * p1 - 3 * p2 + p3) * t3
            );
            splinePoints.Add(point);
        }
    }
    splinePoints.Add(pathNodes[^1]);
    return splinePoints;
}

Step 3: Enforce Obstacle Avoidance for Curves

Even with smooth curves, you need to ensure they don't clip through obstacles:

  • Sample and check: After generating your spline, iterate through each sample point and use Physics.OverlapSphere (with a radius matching your agent/collider size) to check for collisions.
  • Fall back to original nodes: If a segment of the spline collides with an obstacle, discard that curve segment and use the original A* node-to-node line instead. You can also split the segment at the collision point and re-smooth around it if needed.

Step 4: Generate Grid Along the Smooth Path

Once you have your collision-free smooth path, generate a grid centered on the path:

  • For each sample point on the spline, create grid cells in a fixed width (e.g., 2 cells left/right of the path direction).
  • Use the same obstacle check from task 1 to mark any cells that overlap with obstacles as unwalkable.
  • Connect adjacent valid cells to form a continuous grid along the path.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:29:26