这是一个很笼统的问题。如果你问 10 个不同的人,你可能会得到 10 个不同的答案。过去我实现了类似的东西,这就是我所做的(经过一长串优化周期)。
在后台线程上运行的模型更新循环应如下所示:
while(true)
{
updateAllModels()
}
正如您所说,当 GL 线程启动时,这将导致问题,因为它很可能会根据已渲染一半的模型渲染视图,这在最好的情况下可能会导致 UI 故障。
处理此问题的直接方法是同步更新:
while (true)
{
synchronized(...)
{
updateAllModels();
}
}
您在此处同步的对象与您将用于同步绘图方法的对象相同。
现在我们有了一种不会导致 UI 出现故障的改进方法,但整体渲染可能会受到非常严重的性能影响,因为所有渲染都需要等到所有模型更新完成,反之亦然 -模型更新需要等到所有绘图完成。
现在,让我们想一想 - 我们真正需要同步什么?
在我的应用程序(太空游戏)中,更新模型时,我需要计算矢量、检查碰撞并更新所有对象的位置、旋转、缩放等。
在所有这些事情中,视图唯一关心的是位置、旋转、缩放和其他一些 UI 需要了解的小问题,以便正确渲染游戏世界。渲染过程不关心游戏对象的矢量、AI 代码、碰撞测试等。考虑到这一点,我将更新代码更改为如下所示:
while (true)
{
synchronized(...)
{
updateVisibleChanges(); // sets all visible changes - positions, rotations, etc
}
updateInvisibleChanges(); // alters vectors, AI calculations, collision tests, etc
}
和以前一样,我们正在同步更新和绘制方法,但是这一次,临界区比以前小得多。本质上,应该在 updateVisibleChanges 方法中设置的唯一内容是与应该渲染的对象的位置、旋转、缩放等有关的内容。之后执行所有其他计算(通常是最详尽的计算),并且不会停止渲染。
此方法的另一个好处 - 当您执行不可见的更改时,您可以确保所有对象都处于它们需要的位置(这对于准确的碰撞测试非常有用)。例如,在最后一个方法之前的方法中,对象 A 移动,然后对象 A 测试与尚未移动的对象 B 的碰撞。有可能在对象 A 测试碰撞之前移动了对象 B,会有不同的结果。
当然,我展示的最后一个示例并不完美 - 您仍然需要挂起渲染方法和/或 updateVisible 方法以避免冲突,但我担心这将始终是一个问题,关键是最大限度地减少您在任一线程敏感方法中所做的工作量。
希望这会有所帮助:)