Constant Velocity Jitters in SpriteKit

737 views Asked by At

I'm applying a constant velocity to one of my nodes like this in the update function:

// Set a constant velocity to the right:
node.physicsBody?.velocity.dx = 300

When I print the velocity in the didSimulatePhysics function, it prints out around 290. Ok, I'm losing some velocity to linearDamping, makes sense. But it doesn't stay constant.

Every 10-15 seconds there will be an unexplained jitter in the velocity (from the didSimulatePhysics print). For 6 or 7 frames, the velocity will fluctuate from 285-295. Slower, then faster. So I'll get a 287, then a 294, then a 286, then a 294. Never two slow or two fast in a row.

This is my main character, tracked by my camera, and the small change in velocity makes the camera appear to jitter whenever this happens.

I'm far away from any collisions, but note that I am ignoring collisions on this node and have restitution set to 0:

node.physicsBody?.collisionBitMask = 0
node.physicsBody?.restitution = 0

Is the physics simulation lagging and then trying to make up for it on the next frame (FPS is pegged at 60)? Or possibly running into rounding issues?

Is there a way to get an exactly constant velocity in one direction on every frame?

Adding an example of the actual change in node.position.x per frame when moving straight through the air with no collision, setting a velocity.dx of 300 every update:

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
1

There are 1 answers

0
Leszek Szary On

The problem with SpriteKit physics is that it is using a variable time step which does not work well especially with constant movement. This mean that SpriteKit updates your physics in each frame with deltaTime that passed from the last frame. This time is never exactly the same even if you maintain constant 60 FPS. To solve this problem it might be a good idea to use a constant time step for physics simulation. Unfortunately in SpriteKit there is no way to control the time step for physics simulation and it is always tied to the frame rate. If you would use an engine which allows to update physics manually you could implement constant time step for physics simulation for example in the following way:

-(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;
  }
}

Unfortunately in SpriteKit you can't control this and this is the reason why you will always see some small jitters even at 60 FPS in constant movement. You have few solutions:

  • ignore this and just live with it
  • try using different physics engine for example Chipmunk or Box2D
  • do not use any physics engine at all

You can also find more information about variable/constant time step for physics here: https://gamedev.stackexchange.com/questions/1589/when-should-i-use-a-fixed-or-variable-time-step