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

如何使用列表与数组向封闭区域填充GameObject?应采用何种填充算法?

封闭网格区域GameObject填充方案

你当前编写的固定方向嵌套循环逻辑仅支持规则矩形边界的填充,无法适配任意形状的封闭轮廓,实现该需求最适配的算法是*洪水填充(Flood Fill)*算法。

算法核心逻辑

从一个确定位于封闭区域内部的种子点出发,按你设定的填充步长(你代码中使用的10单位)向四周相邻网格点扩展,遇到边界点位、已填充过的点位就停止扩展,直到遍历完所有区域内的可用点位。
为避免填充区域过大时递归触发栈溢出,优先使用队列实现的广度优先迭代版,示例代码如下:

// 填充步长,和边界Cube的放置间隔保持一致
public float fillStep = 10f;
// XZ平面的4个扩展方向,需要支持对角线填充可新增4个对角方向
private Vector2[] extendDirs = new Vector2[] {
    new Vector2(1, 0), new Vector2(-1, 0),
    new Vector2(0, 1), new Vector2(0, -1)
};

public void FillClosedArea(Vector3 seedPos)
{
    // 校验种子点合法性:不在边界上、未被填充过
    if (IsExists(seedPos)) return;
    
    Queue<Vector3> fillQueue = new Queue<Vector3>();
    fillQueue.Enqueue(seedPos);
    // 记录已处理点位,避免重复入队
    HashSet<Vector3> processedPoints = new HashSet<Vector3>();
    processedPoints.Add(seedPos);

    while (fillQueue.Count > 0)
    {
        Vector3 currentPos = fillQueue.Dequeue();
        // 放置填充Cube
        PutACube(currentPos);
        
        // 遍历所有方向扩展
        foreach (var dir in extendDirs)
        {
            float nextX = currentPos.x + dir.x * fillStep;
            float nextZ = currentPos.z + dir.y * fillStep;
            Vector3 nextPos = new Vector3(nextX, currentPos.y, nextZ);
            
            // 点位未处理、不在边界上则加入队列
            if (!processedPoints.Contains(nextPos) && !IsExists(nextPos))
            {
                processedPoints.Add(nextPos);
                fillQueue.Enqueue(nextPos);
            }
        }
    }
}

使用注意事项

  • 种子点必须确保完全位于封闭区域内部,可在用户绘制完封闭轮廓后,取轮廓包围盒的中心点校验通过后作为种子点
  • IsExists方法需要能准确识别边界点位和已填充点位,避免填充超出轮廓范围
  • 若需要适配斜向的封闭轮廓,可以在扩展方向数组中增加对角线方向

填充需求示例图

内容的提问来源于stack exchange,提问作者Muhammet Ali Gözalan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 07:57:03