【问题标题】:touchesMoved called at irregular intervalstouchesMoved 不定期调用
【发布时间】:2014-01-20 19:11:56
【问题描述】:

我正在为 iOS 制作一个游戏,你主要在屏幕上拖动大对象。当我每隔 5 分钟左右在实际的 iPad/iPhone 上运行游戏一段时间(在屏幕上连续拖动对象)时,拖动的对象会卡顿大约 10-30 秒。然后,它又恢复如丝般顺滑。

从视觉上看,游戏的帧速率似乎有一段时间下降到 15 fps,但实际上它一直以坚如磐石的 60 fps 运行。但是,我注意到唯一不流畅的是被拖动的对象,而游戏的其余部分都运行得非常流畅。

这让我相信口吃与 iOS 中的触摸输入有关。所以我开始查看 touchesMoved,发现它通常每 16 毫秒调用一次(因此触摸输入以 60 fps 运行)。到目前为止一切顺利。

然后我注意到当对象开始卡顿时,touchesMoved 开始以奇怪的时间间隔被调用,在 8 毫秒到 50 毫秒之间剧烈波动。

因此,当触摸屏处于这种奇怪的状态时,有时 touchesMoved 会在上一次调用后 8 毫秒被调用,有时会在前一次调用后 50 毫秒后被调用。当然,这会使拖动的对象看起来很不稳定,因为它的位置会不定期地更新。

您知道是什么原因导致 touchesMoved 像往常一样停止定期调用吗?


奖金:

-每当我倾斜屏幕以强制改变屏幕方向时,大约 70% 的时间触摸屏会进入上述状态,即开始不规则地调用 touchesMoved。然后在 10-20 秒后恢复正常,一切都恢复正常。

-我在两部 iPad 和两部 iPhone 上尝试过这个,分别是 iOS 6 和 7,所有这些设备都出现了这个问题。

-OpenGLES 视图用于显示图形。它使用CADisplayLink 与显示刷新率同步。

-我用来测试的 Xcode 项目是由 unity3d 游戏开发工具生成的,但我发现几个非统一游戏出现了同样的问题。这似乎是一个系统范围的问题。请注意,我正在使用 CFAbsoluteTimeGetCurrent 测量 Objective-c 中的时间,完全在统一之外。

【问题讨论】:

  • touchedMoved:在主线程的运行循环中执行。我会使用工具来采样您的应用程序在此期间在主线程上所做的事情,以验证您的应用程序在这些期间没有表现出不同的行为并在主线程上更频繁地执行代码或阻塞。你在用锁吗?

标签: ios cocoa-touch unity3d timing touchesmoved


【解决方案1】:

这不是 Unity 中的错误。

操作系统内部的某些东西进入了错误状态,触摸拖动消息停止顺畅流动。有时您会在一个框架中获得多个更新,有时您不会获得任何更新。

在 iPhone4 或更低版本或游戏以 30Hz 帧速率运行时不会出现此问题。

我在使用我在以前的公司工作时编写的内部引擎时遇到了这个错误。它在升级拼字游戏类型游戏的 UI 系统后首次显现,您可以在屏幕上拖动图块。这太奇怪了,我从来无法确定确切的复制步骤,但它们似乎与时间有关,不知何故。

它也可以在愤怒的小鸟(除非他们现在已经修复)和市场上的其他各种游戏中看到,基本上任何带有触摸拖动滚动或移动的游戏。对于愤怒的小鸟,只需进入一个关卡并开始横向滚动即可。大多数时候它会如丝般顺滑,但可能有十分之一的时候会显得笨重。重新启动应用并重试。

解决方法是将输入更新频率降低到 30Hz 几帧。这会以某种方式震动操作系统的内部结构,并让它有时间理顺自己,所以当你把它调回 60Hz 时,它会再次平稳运行。

只要检测到已进入不良状态,请执行此操作。

【讨论】:

  • 感谢您的精彩解释,您能否说明如何将输入更新频率降至 30Hz? (我猜这是原生 iOS 的东西,与 Application.targetFrameRate 不同)
【解决方案2】:

我也遇到过这种情况。我可以验证它是 Unity 4.3.x 中的一个错误。 我的 4.2.x 在每帧上使用 TouchPhase.Moved 在 60Hz 的设备上构建过程触摸。 我的 4.3.x 构建获得 20-40Hz,TouchPhase.Stationary 在丢帧时发出。

TestFlight 历史记录在这里拯救了我的理智。

别忘了向 UT 提交错误。

【讨论】:

  • 我已经向统一和苹果提交了一个错误。苹果表示他们不会提供帮助,因为该项目引用了外部库(在这种情况下是统一的)。 unity的人已经研究了一个月左右,但到目前为止还不能保证它会得到修复。如果可以的话,请统一提交你自己的错误并在推特/脸书上唠叨他们。
  • 另外,您是否设法找到解决方法或其他方法?看了你的消息后我还不清楚。
【解决方案3】:

这是一场真正的灾难。有时它是滞后的,有时它真的很顺利。即使 GPU 和 CPU 利用率低于 10%,它也会滞后。这不是 Unity 错误。我正在使用 cocos2d v3。 如果有人找到了治疗方法,请发布!

【讨论】:

    【解决方案4】:

    我也遇到过这个问题。我目前仍需验证的假设是,如果您要求给定的帧速率(例如 60 fps),但您实际实现的帧速率低于该值(例如 45 fps),这会导致两者之间的时间/竞争条件问题Unity 以比实际运行速度更高的帧速率从 iOS 请求输入。但是,如果您将其设置为 30fps(至少在我使用 iOS 9.1 进行的 UNity 5.2 测试中),那么您将获得稳定的 30Hz 输入。当我禁用一部分游戏并且它以非常稳定的 60fps 运行时,我会始终从触摸屏获得 60Hz 的输入。这就是我现在所拥有的,但我必须在一个我还没有时间做的简单项目中证明这一点。希望这对其他人有帮助。

    【讨论】:

      【解决方案5】:

      我在这里找到了这个问题的潜在解决方案:https://forums.developer.apple.com/thread/62315(在此发帖是因为我经过大量研究才偶然发现该链接,而这个 StackOverflow 问题是 Google 的第一个结果)。

      为了跟进此事,我对我向 Apple 提交的错误报告做出了回应。这 是回应:

      “只要您不导致任何显示更新,屏幕就会停留在 低功耗,因此 30hz 模式,这反过来也保持事件 输入流以 30 赫兹下降。一种解决方法是实际导致 显示每次接收到的移动的更新,即使它只是一个像素 如果需要输入而没有明确的屏幕更新将移动视图 被触发。”

      在我的应用程序中,使用 GLKView,我将其设置为 preferredFramesPerSecond 到 60。有时,我的输入速率会 随机降到30hz。苹果的回应并未完全解释 为什么会发生这种情况,但显然是预期的处理方法 这是在拖动时直接从 touchesMoved() 调用 display()。

      我对 GLKView 进行了子类化,并将 preferredFramesPerSecond 设置为 60。 touchesBegan(),我设置 isPaused=true,然后开始调用 display() 在 touchesMoved() 中。在 touchesEnd() 上,我设置了 isPaused=false。正在做 这个,我不再有任何问题 - 该应用程序性能更高 比以往任何时候都好。

      Apple 的示例 TouchCanvas.xcodeproj 从内部进行所有绘图 touchesMoved() 也是如此,所以我想这是处理的预期方式 这个。

      【讨论】:

        【解决方案6】:

        据我所知,实现平滑外观的最佳选择可能是在触摸事件之间进行插值,而不是立即将对象映射到触摸位置。

        tl;dr:似乎只是有一个CADisplayLink 导致任何 OpenGL 上下文 Metal 设备以 60fps 的速度绘制可能会导致这种情况。


        我在装有 iOS 10.2.1 的 iPhone 7 Plus 上重现了这个。

        我使用带有preferredFramesPerSecond = 60 的 CADisplayLink 制作了一个小示例简单应用程序,并尝试了以下渲染方法:

        1. GLKViewdisplay()
        2. CAEAGLLayer,按照Apple at WWDC 的规定使用(不透明,唯一图层,全屏,上面没有绘制任何内容)
        3. MTLDevice

        在每种情况下,渲染方法只会清除屏幕,而不尝试绘制任何其他内容。

        在每种情况下,我都看到了输入率问题。


        当在touchesMoved 内部调用时,以下“技巧”似乎也无济于事:

        1. 呼叫glkView.setNeedsDisplay()enableSetNeedsDisplay 设置为true
        2. 移动其他视图
        3. 调用glkView.display()(实际上,它似乎可以将您的输入速率提高到每秒 40 个事件。但据我所知,它看起来并没有更好,而且似乎这样做是错误的,所以我不会不推荐。)

        在运行了所有这些测试之后,我放弃了。相反,我在触摸位置之间插入我的对象。所以这也是我推荐的。

        但我想我会在此处包含我的研究,以防其他人尝试并找到更好的解决方案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多