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

Unity进入Play Mode时编辑器崩溃问题排查(附代码)

Unity道路生成器Play Mode崩溃排查与修复方案

核心崩溃原因及对应解决方案

1. 无限递归调用(最可能触发崩溃)

在GenerateLevel的异常捕获逻辑中,当GenerateRoad抛出异常时,会调用ReBuild(length, chanceOfTurn),而ReBuild又绑定了GenerateLevel方法,这会触发无限递归生成,瞬间创建大量道路对象导致内存爆炸,直接让编辑器崩溃。

修复代码:

catch (Exception exception)
{
    Debug.LogException(exception);
    // 移除递归重建,改为单次终止流程,避免无限循环
    Debug.LogError("道路段生成失败,终止关卡生成流程");
    return;
}

2. 线程操作违反Unity规则

Unity的Instantiate、Transform修改等操作必须在主线程执行,你尝试的Task.Delay和新线程逻辑会让代码脱离主线程,直接触发编辑器崩溃。

修复方案:用协程分批生成避免卡顿

// 替换原同步GenerateLevel为协程版本
public IEnumerator GenerateLevelCoroutine(int length, int chanceOfTurn, int seed)
{
    if (!enabled)
        throw new Exception("生成器未启用,无法生成关卡");

    drivenDistance = 0;
    random = new Rand(seed);
    map = new bool[GameManager.WORLD_SIZE, GameManager.WORLD_SIZE];

    Vector3 startPosition = carBehaviour.transform.position;
    startPosition.y -= 20f;
    transform.SetPositionAndRotation(startPosition, Quaternion.Euler(0, 0, 0));

    for (int i = 0; i < length; i++)
    {
        if (!enabled)
            yield break;

        try
        {
            GenerateRoad(1, transform.rotation, random, ramps);
        }
        catch (Exception exception)
        {
            Debug.LogException(exception);
            Debug.LogError("道路段生成失败,终止流程");
            yield break;
        }
        
        if (random.Next(0, chanceOfTurn) == 0)
            CreateTurn(random.Next(0, 2) == 0 ? 'r' : 'l');

        if (random.Next(0, 10) == 0 && breaks)
            CreateBreak(transform.position, transform.rotation);

        // 每生成10段暂停一帧,避免单帧负载过高(可选)
        if (i % 10 == 0)
            yield return null;
    }

    CreateFinish(transform.position, transform.rotation);
    OnLevelBuilt();
    Dispose();
}

// 修改Start方法启动协程
void Start()
{
    try
    {
        StartCoroutine(GenerateLevelCoroutine(50, 7));
    }
    catch
    {
        Debug.LogWarning("生成新关卡失败,加载列表中第一个存档关卡");
        manager.LoadLevel(1);
    }
}

3. 数组越界未彻底拦截

现有代码仅捕获IndexOutOfRangeException但未终止后续逻辑,越界后的错误操作可能导致内存混乱引发崩溃。

修复代码:先判断索引合法性再操作数组

// 在GenerateRoad和CreateRoadPart中替换原索引操作逻辑
int x = (int)Math.Round(transform.position.x / 10 / SIZE) + GameManager.WORLD_SIZE / 2;
int y = (int)Math.Round(transform.position.z / 10 / SIZE) + GameManager.WORLD_SIZE / 2;

// 先检查索引是否在合法范围内
if (x >= 0 && x < GameManager.WORLD_SIZE && y >= 0 && y < GameManager.WORLD_SIZE)
{
    if (map[x, y])
        manager.ResetLevel(); // 注意:需确保ResetLevel不会触发重复生成逻辑
    map[x, y] = true;
}
else
{
    Debug.LogWarning($"索引[{x}, {y}]超出map数组范围,最大值为[{GameManager.WORLD_SIZE-1}, {GameManager.WORLD_SIZE-1}]");
    return; // 终止当前生成流程,避免后续错误
}

4. 空引用未提前拦截

CreateRoadPart中先执行Instantiate再判断对象是否为空,若预制体本身为空,Instantiate会返回null,后续访问road.transform会直接抛出空引用异常导致崩溃。

修复代码:提前检查预制体合法性

private GameObject CreateRoadPart(GameObject prefab, Quaternion rotation)
{
    // 先检查预制体是否为空
    if (prefab == null)
    {
        Debug.LogError("道路预制体未赋值,无法生成");
        return null;
    }
    
    GameObject road = Instantiate(prefab, transform.position, rotation * Quaternion.Euler(0, 90, 0));
    if (road == null)
    {
        Debug.LogError("道路对象生成失败");
        return null;
    }
    
    road.transform.localScale = new Vector3(SIZE, SIZE, SIZE);
    Rigidbody rb = road.GetComponent<Rigidbody>();
    if (rb != null)
        rb.constraints = RigidbodyConstraints.FreezeAll;
    road.transform.SetParent(world);

    if (prefab == roadPrefab)
        manager.level.road.Add(road);
    else if (prefab == roadTurnPrefab)
        manager.level.turns.Add(road);

    // 索引检查逻辑同上...
    return road;
}

5. ResetLevel引发重复生成

若manager.ResetLevel()方法会销毁现有道路并重新调用生成逻辑,会导致嵌套生成,瞬间创建大量对象引发内存溢出。

修复建议:
在ResetLevel中先停止当前的生成协程,再清理现有道路对象,避免重复触发生成流程。

快速验证步骤

  1. 先注释掉GenerateLevel中catch块里的ReBuild调用,运行看是否还崩溃——若不崩溃,说明无限递归是核心问题。
  2. 检查所有道路预制体(roadPrefab、roadTurnPrefab等)是否在Inspector中正确赋值。
  3. 切换为协程生成方式,避免单帧生成过多对象导致内存峰值过高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 02:18:11