我的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";
}
}
鉴于您正在实例化对象,我建议使用以下路径:
- 将协程更改为简单的函数调用,因为循环迭代之间似乎不需要任何延迟,这是在 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 只能在主线程中使用......