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

Unity随机地图生成脚本陷入死循环问题求助

问题分析与修复方案

问题根源

  1. 固定坐标重复循环:原代码中randomx和randomy仅在循环外生成一次,循环内反复使用同一位置,若该位置不满足接触地面条件,会陷入无效循环。
  2. 检测时机不匹配:CheckSurrounding的isTouching在Update中更新,而while循环在单帧内同步执行,循环过程中Update不会触发,导致检测值始终为初始状态,无法正确判断当前位置。

修复后的代码

MapGen 脚本(核心生成逻辑)

public class MapGen : MonoBehaviour
{
    public GameObject prefab1;
    public LayerMask groundLayer;
    private Vector3 prefab1Position;

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            SpawnPrefabOnGround();
        }
    }

    public void SpawnPrefabOnGround()
    {
        GameObject newObj = null;
        int counter = 0;
        const int maxAttempts = 1000;
        bool spawnSuccess = false;

        while (!spawnSuccess && counter < maxAttempts)
        {
            counter++;
            // 每次循环生成新的随机坐标
            float randomX = Random.Range(0, 10f);
            float randomY = Random.Range(0, 10f);
            prefab1Position = new Vector3(randomX, randomY, 0f);

            BoxCollider2D prefabCollider = prefab1.GetComponent<BoxCollider2D>();
            if (prefabCollider == null)
            {
                Debug.LogError("Prefab1 缺少 BoxCollider2D 组件!");
                break;
            }

            // 实时检测当前位置是否接触地面
            bool isTouchingGround = Physics2D.OverlapBox(prefab1Position, prefabCollider.bounds.size, 0f, groundLayer);

            if (isTouchingGround)
            {
                newObj = Instantiate(prefab1, prefab1Position, Quaternion.identity);
                spawnSuccess = true;
            }
        }

        if (!spawnSuccess)
        {
            Debug.Log("尝试 " + maxAttempts + " 次后仍未找到合法地面位置");
        }
    }
}

可选:优化后的 CheckSurrounding 脚本(若需实时检测)

如果需要保留物体生成后的实时地面检测功能,可修改该脚本:

public class CheckSurrounding : MonoBehaviour
{
    public bool isTouching;
    public LayerMask GroundLayer;

    void Start()
    {
        if (GetComponent<BoxCollider2D>() == null)
        {
            Debug.LogError("当前物体缺少 BoxCollider2D 组件!");
        }
    }

    // 主动检测方法,支持外部调用
    public bool CheckTouchingGround()
    {
        BoxCollider2D collider = GetComponent<BoxCollider2D>();
        if (collider == null) return false;
        return Physics2D.OverlapBox(transform.position, collider.bounds.size, 0f, GroundLayer);
    }

    void Update()
    {
        isTouching = CheckTouchingGround();
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        BoxCollider2D collider = GetComponent<BoxCollider2D>();
        if (collider != null)
        {
            Gizmos.DrawWireCube(transform.position, collider.bounds.size);
        }
    }
}

关键优化点

  • 每次循环重新生成随机坐标,避免重复无效位置
  • 直接在生成逻辑中执行物理检测,无需依赖Update帧更新,确保检测结果实时有效
  • 先检测位置合法性再实例化物体,减少不必要的性能开销
  • 限制最大尝试次数,避免过度消耗性能

内容的提问来源于stack exchange,提问作者erdem.61

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 03:44:50