NSTimer与CACurrentMediaTime()的区别

24

我正在进行我的第一个iOS游戏,正在苦恼如何最好地集成对象移动。

该游戏在快速移动的对象和不断变化的快速用户输入方面非常依赖。因此,我正在尽力使对象集成和约束求解程序尽可能快速地运行且准确(以最小化连续游戏循环调用之间的用户输入更改)。

具体来说,我不确定NSTimer类和CACurrentMediaTime()函数的能力。这很难经验性地测试,因为我不确定哪个误差更大。例如,使用重复间隔为0.008的NSTimer(约2次更新/屏幕刷新),并在连续调用中调用CACurrentMediaTime(),我发现调用之间的时间间隔从0.0075到0.009不等。很难说哪个负责(小)不一致性。因此,对于确定时间步骤,我应该:

  1. 假定NSTimer足够准确,使用NSTimer时间间隔作为游戏循环的时间步长

  2. 使用CACurrentMediaTime()确定连续游戏循环调用之间的时间间隔。

我是学生并且对这些都是新手 - 请友善点 :) 任何建议都非常感谢。谢谢你的时间。

2个回答

41

NSTimer 并不是一个实时计时器,它甚至离实时计时器很远,也不打算成为实时计时器。如果你需要的时间间隔小于半秒,NSTimer 不是合适的工具。对于小于一秒的事情,我甚至都不建议使用它。但对于多秒或多分钟的任务,当你不需要精确知道它何时触发时,NSTimer 是个好选择。我经常使用它。

CACurrentMediaTime() 不是计时器,它是包装系统中最精确时间函数 mach_absolute_time() 的函数。因此,如果你真的关心现在的时间,并想以人类可理解的数字形式表示,CACurrentMediaTime() 就是你需要的函数。虽然 mach_absolute_time() 可以给出非常精确的时间,但它基于Mach 绝对时间单位,这并不是人们熟悉的时间标准(每个 CPU 都有不同的时间尺度)。因此,我们有了 CACurrentMediaTime() 让我们的生活更轻松。

那么,NSTimer 并不适合实时计时器,CACurrentMediaTime() 也不是计时器。那么游戏程序员该怎么办呢?

Grand Central Dispatch包括一些我们拥有的最好的“在大约这个时间运行此项任务”的系统之一。这就是Dispatch Source。我说“大约这个时间”,因为GCD仍然不是RTOS人员所指的实时方式。但对于游戏开发者来说,它已经足够实时了。请查看Concurrency Programming Guide中“创建计时器”的部分以及适用于单次延迟的dispatch_after()函数。

请记住,任何在主线程(UI线程,执行所有绘制操作的线程)上运行的都会与该线程上的所有其他内容共享时间。因此,通常需要在后台线程上进行计算,同时在主线程上处理绘图和用户交互。这就是GCD dispatch_queues旨在帮助您解决的问题。另一方面,需要记住许多iOS设备是单核的。因此,“后台线程”有点不准确。CPU一次只能真正运行一件事情。这就是将事情移动到GPU非常重要的原因(见下文)。

您还可以认真看待像cocos2d这样的系统,它是一个非常好的游戏引擎。它为您处理了许多这些细节,让您专注于游戏部分。

如果你使用苹果的框架,你应该看看核心动画(Core Animation)。如果你正在使用定时器来移动屏幕上的物体,那么你不应该这样做。核心动画是如何在屏幕上移动物体的。它为你处理了很多细节,比你自己做得更快,使用电池更少,并且将很多工作转移到了GPU(如上所述)。它更多地设计用于UI元素而不是游戏,但它肯定可以用于构建简单的游戏。

当然,还有GLKit,但那是完全不同的东西....


3
嘿 Rob,感谢你给出的精彩回答!我非常感激你抽出时间仔细阅读并作出回复。谢谢! - Z.O.
感谢您详细的回复!快速澄清一下:正如下面一个答案所建议的那样,NSTimer文档声称“计时器时间间隔的有效分辨率受限于大约50-100毫秒的数量级。”您对避免使用NSTimer处理亚秒任务的建议今天是否仍然适用?再次感谢! - Crashalot
1
我仍然不会那么快地使用NSTimers(尤其是带有选择器的)。运行循环和调度开销似乎过高。可能我对它们过于谨慎,但NSTimer似乎不是正确的工具。(现在有基于块的接口,这些接口可能完全建立在GCD而不是运行循环之上,所以那些可能完全没问题,但我还没有深入探索新的接口。) - Rob Napier

4
根据NSTimer文档的说明,计时器的时间间隔有效分辨率限制在50-100毫秒左右,这可能是您看到时间间隔变化的原因。
我建议您将更新间隔更改为0.016秒,因为没有理由让游戏状态更新得比屏幕绘制更频繁。然后,您可以使用CADisplayLink来处理定时。由于它使用显示器的刷新率,所以应该非常准确。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接