应用/游戏在协程运行时完全冻结



我的Android ARCore Unity app/game在协程运行时冻结,然后在协程完成后恢复。协程位于附加到游戏对象的脚本中,协程在 Start(( 函数中调用。我尝试将yield return null;插入协程的更多部分,这减少了暂停的时间,但增加了更多的暂停,导致在对象实例化后一两秒钟内非常不稳定(基本上不存在(的游戏玩法。这可能是因为 ARCore 不支持多线程渲染吗?如果是这种情况(或不是(,我该如何解决这个问题,所以我的协程在对象实例化后运行(我猜"在后台"(,因此它不会影响游戏 FPS?

这是我的代码:

void Start() 
{
    StartCoroutine(MyCoroutine());
}
IEnumerator MyCoroutine ()
{
    yield return null;
    Transform[] allChildren = GetComponentsInChildren<Transform>();
    foreach (Transform child in allChildren)
    {
        if (child.gameObject.GetComponent<MeshFilter>())
        {
            if (!child.gameObject.GetComponent<MeshCollider>())
            {
                child.gameObject.AddComponent<MeshCollider>();
            }
        }
        child.gameObject.tag = "CenterObject";
    }
}

协程在构造协程时似乎有开销,如下所述:https://forum.unity.com/threads/startcoroutine-performance-cost.233623/

鉴于您正在实例化对象,我建议使用以下路径:

  • 将协程更改为简单的函数调用,因为循环迭代之间似乎不需要任何延迟,这是在 Unity 中使用协程的主要思想。您还将添加碰撞体并期望游戏继续,如果需要注册碰撞,这可能会导致意外行为。
  • 如果可能,实例化预先附加了碰撞器的预制件。
  • 使用对象池,您可以在游戏开始之前创建对象并在需要时激活它们,并在必要时在销毁它们时禁用它们。

这是因为您在协程中陷入循环。您需要将产量移动到循环内部:

IEnumerator MyCoroutine ()
{
    Transform[] allChildren = GetComponentsInChildren<Transform>();
    foreach (Transform child in allChildren)
    {
        if (child.gameObject.GetComponent<MeshFilter>())
        {
            if (!child.gameObject.GetComponent<MeshCollider>())
            {
                child.gameObject.AddComponent<MeshCollider>();
            }
        }
        child.gameObject.tag = "CenterObject";
        yield return null;
    }
}

即便如此,如果这是您循环通过的大量孩子,这可能只是一个性能问题。

除了修复协程的答案:

协程并不是真正的多线程!这就是如果协程中有较长的任务,您的应用程序会冻结的原因。

协程的yield return只是让做一个快速动画或类似的东西变得容易/懒惰,因为协程有点"记住"他们离开的地方并从这一点开始(用简单的话说(,所以你可以运行很多显然"并行"的东西。但是它仍然都在同一个线程中运行,所以实际上它似乎只是并行执行的,因为一切都在两个帧之间执行。

如果您确实想在另一个线程中执行耗时的任务,请查看异步等待,这是自Unity 2017以来Unity真正的多线程。

但是,Unity 不是线程保存,这意味着大多数 API 只能在主线程中使用......

最新更新