8

我正在为 Unity iOS 开发一个非常简单的垂直滚动游戏。我的游戏出现不一致的抖动。我在网上广泛搜索了一个没有任何运气的解决方案。我正在使用 Unity 版本 5.3.4 f1。

游戏

游戏截图

  • 一个角色正在倒下。我们正在使用统一的角色控制器来移动角色Update()Time.deltaTime正在成倍增加)。
  • 相机正在跟随中的角色LateUpdate()Vector3.Lerp()用于跟随)。
  • 由于角色正在向下移动,因此障碍物似乎正在向上移动屏幕。
  • 场景中有 1 个定向光,用于设置实时阴影。阴影质量是高阴影和硬阴影。
  • 场景中没有刚体。并且探查器中没有大的尖峰。
  • 我们有非常简单的几何图形和很少的绘图调用/设置传递调用(平均 7 个设置传递调用)。
  • 我们有恒定的 60 fps。
  • 由于我们在 iOS 上运行 vSync 默认为 On 且无法禁用。

问题

  • 背景元素/障碍物(树木、岩石等)无缘无故开始抖动。行为不一致,有时会抖动,有时不会。
  • 即使它没有抖动,当用户通过触摸进行输入时,我们也会遇到小的卡顿。

我们尝试过的

  • 我们已经尝试了Update(), LateUpdate(), FixedUpdate(), Time.deltaTime Time.smoothDeltaTime, Lerp 的所有组合,将场景减少到几个立方体并移除所有对撞机和触发器。
  • 我们已经研究了以下线程:Link1Link2Link3和无数其他线程。
  • 最初,我们的游戏以默认的 30 fps 运行。但经过一番研究,我们的问题似乎是由于“帧率”和“屏幕刷新率”之间的差异。(要了解此问题,请参阅以下链接)。由于 iOS 设备的刷新率为 60Hz,我们将目标帧率设置为 60,并且我们的游戏保持恒定的 60 fps。
  • 将目标帧速率设置为 60 后,抖动有所改善,但现在不一致。

我完全没有想法。任何帮助或指针将不胜感激。

提前致谢。

4

3 回答 3

1

谢谢大家的时间。

  1. 不,这不是浮点进动错误。
  2. 我们在运行时实例化对象但是当问题发生时我们切换到对象池但它没有帮助。
  3. 我已经完成了彻底的分析,甚至在设备和垃圾收集器上进行远程分析也不是问题。

经过进一步研究,我遇到了一篇博客文章,这些人面临着几乎类似的问题,并且解决方案在我的场景中有效。

简而言之,问题在于统一帧与设备的帧绘制速率不同步。当 Unity 需要更长的时间来渲染其帧时,设备渲染循环不会等待 unity 完成并绘制一个导致抖动的空帧。但是,正如我在文章标题“Inconsistent Jitter”中所说,博客也报告了同样的情况,因此它不会一直发生。

你怎么知道这是同一个问题?好吧,您会Render在分析器中看到尖峰(尽管我们有非常简约的几何形状)。它看起来更像是渲染发疯了。

尽管该博客更多地是关于输入变得滞后,但它在我的场景中也有所帮助。有些人可能不明白如何为他们解决这个问题,我推荐这个POST,它提供了一个非常清晰的解决方案。

为了进一步研究,当名为“cgJames”的用户跳转到CONVERSATION时开始阅读。

我希望这对其他人也有帮助。

于 2016-08-08T07:26:37.690 回答
1

这可能是由许多不同的原因引起的,在没有看到任何代码的情况下,我只能提出一些想到的建议:

1.浮点精度误差

  • 角色是否不断下降?
  • 角色跌倒一段时间后会出现错误吗?

那将指向浮点精度错误。不要让角色跌落,而是将角色周围的对象从屏幕视图下方移动到屏幕视图上方,以便一切都发生在原点附近。

2. 经常实例化或其他滞后峰值

  • 你是实例化对象还是池化它们?
  • 您是否正在执行任何长时间的计算?
  • 你有很多for//循环吗foreachwhile

实例化将导致延迟峰值并创建垃圾,这将导致垃圾收集器更频繁地运行。由于帧速率是固定的,当发生慢速操作时,您会看到一些抖动。

当玩家走一段距离时,您应该实例化和破坏对象,而不是Instantiate在场景加载后创建一个 GameObjects 池,使用 使它们处于非活动状态gameObject.SetActive(false),并将它们存储在列表、数组等中,当您需要Instatiate一个新对象时,只需从池中取出一个,Transform.positiongameObject.SetActive(true)在需要时更换它。

3.垃圾收集器经常运行

这个不太可能是一个问题,但仍然提到它。拿这个示例代码:

void Update()
{
    Vector3 someVector = new Vector3(0,0,0);
    float distance = someVector.magnitude;
    if (distance > 5.0f)
        Vector3 someNewVector = someVector + transform.position;
    else
        Vector3 someNewVector = Vector3.zero;
}

每次Update运行时,它都会创建新变量并为它们分配内存。下次更新runs, it creates new variables, and allocates more memory. Eventually, the memory usage sets off the garbage collector, which goes around and frees up the memory used by all the previousUpdate`功能。相反,您应该在开始时分配内存,然后重用变量。

void Start()
{
    Vector3 someVector = new Vector3(0,0,0);
    Vector3 someNewVector = new Vector3(0,0,0);
    float distance = 0f;
}
void Update()
{
    someVector = Vector3.zero;
    float distance = someVector.magnitude;
    if (distance > 5.0f)
        Vector3 someVector += transform.position;
    else
        Vector3 someVector = Vector3.zero;
}

要诊断这一点,您需要附加配置文件调试器并观察抖动是否与垃圾收集器一致。

希望这里的东西可能对您有所帮助。查找抖动源的最佳选择是使用分析器。这是iOS的说明:

将您的 iOS 设备连接到 WiFi 网络(分析器使用本地/临时 WiFi 网络将分析数据从设备发送到 Unity 编辑器)。在 Unity 的构建设置对话框中选中“Autoconnect Profiler”复选框。通过电缆将您的设备连接到 Mac,选中 Unity 构建设置对话框中的“开发构建”复选框,然后在 Unity 编辑器中点击“构建并运行”。当应用程序在设备上启动时,在 Unity 编辑器中打开探查器窗口(窗口->探查器)。

更多信息:探查器窗口

于 2016-08-05T22:28:36.110 回答
0

我最近遇到了同样的问题。完全正确... Unity 中的垂直滚动条,图形简单,仅在 iOS 上遇到帧率不一致的情况,有时可能与输入有关,也可能与输入无关。

无论如何,我终于找到了问题所在。尝试将 iOS 上的渲染引擎从 Metal 更改为 OpenGL ES 2 或 3。

希望这也能解决您的问题。

于 2017-04-05T08:03:29.397 回答