I’ve been banging my head against a wall today because of a weird error in my SpriteKit game. I have been very busy these days working on some projects and I had put my SpriteKit game on hold meanwhile, so today I decided to start working on it again.
To my surprise, I found that now the hero would suddenly start ignoring the platforms and just fall and die for no apparent reason. As I was coding the projectile emitter nodes, I initially thought that I had somehow messed up the code. So I started examining all changes I had done, got back to previous git commits, discarding changes, but couldn’t find the error. Damn, I even used time machine to get back to prior versions in a frantic attempt to discover what was going on.
Unfortunately, I couldn’t manage to find the problem. So I searched the web, and found some insights that led me to the answer. It seems that there is a bug in iOS 7.1 that would cause the SKSpriteNode to ignore the collisions and contacts (thus rendering its physics body useless) if you set the xScale of the node to -1. The fact is that I was actually using the xScale of the nodes to turn my creatures left (as this is the easiest way to have them face left without having to re-draw all my sprites), so I will have to disable this feature until Apple comes up with a solution.
I have filled a bug request with Apple and I am waiting to hear from them. Will let you know if I receive an answer. Are you facing the same issue? let me know in the comments.
Edit: As Akash points out in the comments, there is a fix that implies reinitializing and setting the properties of the physics body of a SKNode after setting the xScale. However, in some environments (like my game), with potentially dozens of nodes turning and changing direction every iteration, it is a bit of an overkill to re-create their physics body that frequently, so I hope Apple releases a solution quick.
21 Comments
Luis Silva
I have the same issue. I also have been experiencing crashes at a point that the game is restating and removes children from their parent.
Do you know anything about it?
nacho
Hi Luis,
I haven't experienced any strange crashes yet, but if by "restarting" you mean transitioning to a new SKScene (like using a SKTransition), you must take into account that all SKNodes (that includes the SKSpriteNodes) that you are presenting are children of your SKScene or children of nodes that are children of SKScene, so if you create a new scene and transition to it, you must make sure that all pending animations and SKActions are cancelled, and that no new objects (like projectiles) are added to the old scene.
So say you, for instance, have an enemy that periodically generates projectiles and add them to its scene (that's self.scene), that scene will be deleted when you transition to another scene, and if a new projectile is generated (i.e: due to the activation of a NSTimer) and added to the old SKScene (self.scene), it would probably end up in a crash.
Hope it helps.
Luis Silva
Hi Nacho,
Thanks for your help with this.
It actually is like the "play again" kind of reset, it all happens in the same scene, what I do there is to removeFromParent for some SKSpriteNodes and restart the game cycle. This used to work perfectly before updating to iOS 7.1
nacho
Yes, maybe it has something to do with the iOS 7.1. I can definitely confirm the xScale bug. Have you contacted Apple or filled a bug report?
Luis Silva
No yet, but I'll do it.
Thanks.
Akash Gupta
Hi,
I was experiencing the same problem. However, I was able to solve it by re-initialising the physicsBody each time I set the xScale property.
nacho
Thanks for sharing, Akash! In fact, that seems to be a temporary fix, but I think it is a bit of an overkill having to re-create the physics body every time I set the xScale property (in my case it happens a lot during the game, because it is very dynamic), so I guess I would have to wait until Apple releases a fix.
Akash Gupta
That is true. This issue seems even more weird after I discovered that just using the line:
node.physicsBody = node.physicsBody;
Matt
I am finding the same problem, but it's a little inconsistent. I tried:
node.physicsBody = node.physicsBody; right after:
node.xScale = -1;
but that still caused the scaled sprite to fall through the sprite that was supporting it. I suppose I will need to file a bug report also.
nacho
Please, do fill the report. I think the more developers we inform about this issue, the faster will Apple address the problem. In my experience node.physicsBody = node.physicsBody; didn't work either. I had to re-instanciate it by creating a completely new SKPhysicsBody and setting all its properties again, so for me, at the moment, is not a suitable solution.
Matt
So Nacho, you reset your xScale and then on the next line you do something like this: self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bodyRect.size];
And then continue on the set the collision, category and contact test bitmaps as well as other Physicsbody properties again? Does seem roundabout, doesn't it?
Matt
And to be clear, in my case 'self' is the node I'm working with.
nacho
Yes Matt, I recreate the SKPhysicsBody entity and then apply all the masks again (collision, contact, category...) and all the physics properties, but even after all this process, the node keeps on doing weird things, like bouncing like crazy and getting outside of the scene bounds.
Matt
Just curious if you had any success with your bug report with Apple. I filed one, too, but nothing yet. I am in a similar situation as you are, where I have a product ready for delivery but there is erratic behavior with this xScale business, and it's not predictable, as in, it works OK for a while, but then somehow the contact 'breaks' if you will. In my case I have two nodes in contact, one on top of another. If I change the xScale of the top one to -1, it falls right through the bottom one. But again, not always ... frustrating!! When I reset the Physicsbody it slowly starts falling, too. So I'm not really sure what the best hack around this is. Would love to know how you solved it.
nacho
Hi Matt,
I just checked today with the new iOS update, and no luck either. Seems like we'll have to wait for the next patch/release. I have decided to finally release my game anyway. In my case, I just did a dirty fix for the creatures that have to turn left-right (duplicating the sprites for left direction) and prevented the hero from turning left (as he is supposed to go right anyway). I hope they will release a fix for this issue soon, so I can release a proper update for it.
I have noticed the same behavior that you describe, as soon as a SKSpriteNode changes its xScale, it starts ignoring other nodes, collisions and contacts, thus falling to the ground. I agree is really frustrating. Hope you'll find a way to bypass it meanwhile.
Best!
Markus
This is still a bug...I am using two images, one for left and the other for the right orientation of character.
Markus
I am not getting any errors with collisions only when I set xScale after everything else is set.
Like this:
// someNode.xScale = -1;
someNode.name = [NSString stringWithFormat:@"..."];
someNode.position = CGPointMake(...);
someNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(...)];
someNode.physicsBody.dynamic = YES;
someNode.physicsBody.affectedByGravity = NO;
someNode.xScale = -1;//do this after position and physics body is set
I still use two images, because I am not sure is this really works, but if I do it like above, there are no problems with collision.
Ignacio Nieto Carvajal
Agree. Indeed, I don't know how Apple hasn't fixed it for iOS 8. I think it actually got worse, and I think I will have to resort to having two images like you, because otherwise the physics engine gets unusable after changing xScale.
Michael Redig
I didn't read all the comments, but an easy (ish) workaround could be to nest the sprite in an SKNode. Set the physics on the SKNode, then set xScale on the sprite itself.
Ignacio Nieto Carvajal
Thanks Michael,
Unfortunately, I have tried it and the wrapping node also behaves funny. It was because of a bug in SpriteKit in iOS 7.X. It seems to be fixed now.
Imran
This is how i solved it in my case: http://stackoverflow.com/questions/22454220/flipped-x-scale-breaks-collision-handling-spritekit-7-1/29098401#29098401