首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将长期运行的操作逐步转化为一步一步的操作?

将长期运行的操作逐步转化为一步一步的操作?
EN

Software Engineering用户
提问于 2019-03-28 18:25:02
回答 1查看 164关注 0票数 3

我正在联合开发一款电子游戏,在某些时候我面临着一个很难解决的问题:

游戏在加载级别数据时冻结。

,让我列出在这个过程中发生了什么,需要几秒钟:

  • 由截面、面、顶点组成的载荷轨道网格数据
  • 加载轨道纹理,为网格建立一个图集。
  • 使用上述数据建立轨道网格

这个加载过程需要几秒钟的时间,我希望它会更长,因为我将不得不加载更大的景物(还没有完成)。

Considerations:

这个加载过程中的一些步骤不能在后台线程中运行,因为它们实例化了来自Unity的对象,而这些对象只能从其主线程执行,例如创建纹理、网格等。

解决问题的尝试和想法:

  • 启动一个协同线,这是不工作的,因为它们被期望在单个帧内运行,加载过程需要数百个帧,一个帧是1/60秒
  • 将加载分割成块,在每个帧上处理每个进程,这很可能是解决方案,但很棘手。
    • 在需要时,使用dispatcher (即在适当线程中执行的异步调用)生成引擎对象,例如从原始像素创建最终纹理。

我将把重点放在第二种方法,因为它似乎是正确的,但我对另一种方法持开放态度。

问题:

我可以使用什么方法或模式将长时间运行的操作拆分为较小的操作?

(希望你能明白,别告诉我。)

编辑:评论后的澄清:

基本上,我的问题很简单,但很难修复,因为UI冻结了,因为在其中运行的任务需要比通常更长的访问时间;复杂的问题是如何在不重写整个任务的情况下重构它。我相信有一种更简单和同样有效的办法来解决这一问题。

由此产生了另外两个想法:

  • 作为一种Dispatcher方法,我会在后台线程中运行整个过程,根据需要包装引擎调用,UI只会冻结一点;即使在AAA游戏中也是如此。
  • 静态加载屏幕,明显地隐藏了问题,但根本解决不了问题。
EN

回答 1

Software Engineering用户

回答已采纳

发布于 2019-03-29 14:02:00

硬约束

您需要将数据分配给Mesh。这种事必须发生。

没有办法可以绕过它。

Unity并不是线程安全的,所以它必须发生在主线程中。

没有办法可以绕过它。

因此,我们可以在这里建立的是,如果将任何数据分配给网格需要(太长)时间,恐怕这是不能改变的,它需要花费多长时间。然而,它可能正在读取和加载数据,这占用了处理时间的大部分时间。

协联

你的两个想法,“启动协同线”和“将加载分成块”实际上是相同的。这是因为coroutine允许您在性能管理方面做的事情是:“好的,这对这个框架来说已经足够了,让我们在下一个中继续这样做”。

代码语言:javascript
复制
public IEnumerator ExecuteSomethingThatTakesLong()
    {
        for (int i = 0; i < 200; i++)
        {
            // A function that takes time to execute. Doing this 200 times
            // in a row takes about a second, causing a lag.
            TakeTime(10000);

            // By waiting after each step, it will definitely take 200 frames
            // to complete, but no noticable lag occurs.
            yield return null; 
        }
    }

因此,为了从协同中获得您想要的东西,您将不得不“将加载分成块”。问题是,你必须找到一个很好的大小块。如果你发现一个块大小可以正常工作,那么对于性能较差的机器来说,这可能是太大了--而速度较慢的机器会结结巴巴的,因为每一个帧都有点太过了。

当然,这不是一个无法解决的问题;你可以留下一个足够好的空间等等。然而,分割一个3D模型文件并不是没有它自己的挑战,只是进一步复杂化了这一点。

如果您需要为WebGL平台构建,则没有线程,这是解决此问题的唯一角度。然而,从您的问题来看,您似乎在一个允许线程的平台上工作(几乎所有其他平台)。

,我们在这里能做什么,

如果您可以使用线程,那么在这里它们将是更容易的选择。他们说

你有问题了。你用线程来解决它。你现在有两个问题。

我也同意,但在这种情况下,线程似乎是更容易的选择。

幸运的是(或者更确切地说,是因为有人考虑了这个问题),Mesh使用了非常原始的数据;我们在这里讨论的是Vector3s和int[]s。Vector3是Unity的一部分,但它是一个例外,因为它是线程安全的。

为了获得最大的性能收益,我建议制作一个类似Mesh's数据的类。好吧,你需要的部分至少。这样,你就可以在另一个线程中填充所有你需要的数据。当你完成之后,你可以在主线程上一个一个地拷贝每个属性。

如果确实有必要,您还可以使用协同线进一步拆分数据分配(首先分配顶点,下一帧分配三角形,下一帧分配UVs.)。

票数 1
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/389392

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档