Ios SpriteKit中的等速抖动

Ios SpriteKit中的等速抖动,ios,swift,sprite-kit,game-physics,skphysicsbody,Ios,Swift,Sprite Kit,Game Physics,Skphysicsbody,我将恒定速度应用于更新函数中的一个节点,如下所示: // Set a constant velocity to the right: node.physicsBody?.velocity.dx = 300 当我在didSimulatePhysics函数中打印速度时,它打印出大约290。好吧,线性阻尼使我失去了一些速度,这是有道理的。但它并不是恒定不变的 每10-15秒,速度就会出现无法解释的抖动(来自didSimulatePhysics打印)。对于6或7帧,速度将在285-295之间波动。慢一

我将恒定速度应用于更新函数中的一个节点,如下所示:

// Set a constant velocity to the right:
node.physicsBody?.velocity.dx = 300
当我在didSimulatePhysics函数中打印速度时,它打印出大约290。好吧,线性阻尼使我失去了一些速度,这是有道理的。但它并不是恒定不变的

每10-15秒,速度就会出现无法解释的抖动(来自didSimulatePhysics打印)。对于6或7帧,速度将在285-295之间波动。慢一点,然后再快一点。所以我会买287,然后是294,然后是286,然后是294。不要连续两个慢或两个快

这是我的主要角色,由我的相机跟踪,速度的微小变化使相机在任何时候都会出现抖动

我远离任何碰撞,但请注意,我忽略了此节点上的碰撞,并将恢复设置为0:

node.physicsBody?.collisionBitMask = 0
node.physicsBody?.restitution = 0
物理模拟是否滞后,然后试图在下一帧上弥补(FPS定为60)?或者可能会遇到取整问题

有没有办法在每一帧上得到一个方向上的精确恒定速度

添加一个示例,说明在没有碰撞的情况下,在空中直线移动时每帧node.position.x的实际变化,每次更新时将velocity.dx设置为300:

3.82861328125 // this is the norm - thousands of these before this blip)
3.82861328125
3.82861328125
5.740478515625 // blip begins
1.9150390625
3.82861328125
5.740478515625
1.9150390625
5.740478515625
1.9150390625
5.740478515625
1.9150390625
5.740478515625
3.82861328125 // blip ends
3.82861328125
3.82861328125

SpriteKit物理学的问题在于,它使用的是可变时间步长,特别是在不断运动的情况下,这种步长效果不佳。这意味着SpriteKit会使用上一帧传递的deltaTime更新每一帧中的物理。即使保持恒定的60 FPS,这个时间也不会完全相同。为了解决这个问题,在物理模拟中使用恒定的时间步长可能是一个好主意。不幸的是,在SpriteKit中,无法控制物理模拟的时间步长,而且它总是与帧速率挂钩。如果您使用允许手动更新物理的引擎,则可以通过以下方式实现物理模拟的恒定时间步长:

-(void)update:(double)dt
{
  double fixedDt = 1.0/60.0; // or you can put for example 1.0/300.0 to have more physics updates per frame

  self.difference += MIN(dt, 0.1); // prevent too big dt changes

  while (self.difference > fixedDt)
  {
      [self updatePhysics:fixedDt];
      self.difference -= fixedDt;
  }
}
不幸的是,在SpriteKit中,你无法控制这一点,这就是为什么即使在60 FPS的持续运动中,你也会看到一些小的抖动。您几乎没有解决方案:

  • 忽略这一点,接受它
  • 尝试使用不同的物理引擎,例如花栗鼠或Box2D
  • 不要使用任何物理引擎

您还可以在此处找到有关物理的可变/恒定时间步长的更多信息:

关于相机抖动,大多数游戏都会使相机平滑,这样相机将超时移动到位置,而不是瞬间移动,从而使您描述的场景看起来流畅。现在,关于您的实际问题,如果您在更新方法中设置速度(即连续),那么速度应该保持不变。然而,sprite工具包实现了可变的时间步长,因此当帧速率下降时,抖动可能会出现在该位置。您是否在模拟器或设备上运行。你确定没有像重力、摩擦力这样的外力吗?好主意——事实上,我正在向新的位置移动,但这种变化仍然(几乎)可以感觉到,因为相机在其他方面非常稳定。这是在iphone6设备上。FPS表保持在60,CPU约为5%,但看起来确实有点滞后。绝对没有摩擦。重力是开启的(重力是我使用物理节点的原因),但它会影响水平速度吗?每10-15秒只有一次,但只有几帧。也许ARC正在清理一些东西,并导致非常小的帧速率延迟?仪器显示没有CPU峰值。谢谢你的回复,很奇怪。如果您想进一步调试这个问题,您可以通过跟踪sprite kit在更新函数中提供给您的增量时间来查看它是否确实是帧速率。这是因为你不能总是按照SKView FPS显示的内容去做,因为它只是一个平均值。如果你计算自己的增量时间,你可以看到在紧张时刻发生了什么。如果增量时间持续显示1/60,那么您知道抖动运动一定是由其他原因引起的。在示例项目中重现此问题也可能会有所帮助。您可能还希望尝试在发布模式下运行项目,以便消除大量调试开销。最后(这听起来可能很奇怪),你可能想尝试删除应用程序并清理构建文件夹。在我的精灵套件游戏中,很少有构建会非常缓慢,这样做总能解决问题。同样,这可能是一个与你面临的问题完全不同的问题,我只是想给你尽可能多的信息。有趣的(5.740478515625+1.9150390625)/2=3.8277。。。它确实看起来像是过度拍摄,然后纠正下一帧。我怀疑如果你记录每帧的时间,你也会看到一个尖峰。60fps是一个平均值,因为它只是大计划中的几帧,你可能不会看到fps下降,或者更确切地说,它不会报告。至于为什么每10到15分钟就会发生一次,我不确定。我认为10-15是一个估计数。实际上,我会给它计时,看看是否有任何与跳过所需时间的恒常性。