I have been working on my first SpriteKit game that perfectly works on iPhone 6 but not on iPhone 5 (iOS 8.2 on both, written in Swift). I explain my problem: there is a simple ball (a SkShapeNode) that bounces when tapping on the screen. The move is very smooth on iPhone 6 but it has some lagging on iPhone 5 but NOT the first time. The FPS is 60 all the time. I have simplified my project a maximum and I have tried everything, I really need your help so much, I am a little bit desperate. I am ready to try anything, any help would be very appreciated. Thank you so much in advance!
Here is the video (smooth the first time then lagging):
https://www.youtube.com/watch?v=xNxp2uGIJew
Here is the repository if you want to test it:
https://github.com/jonmars8/SpriteKit-Lag-iPhone5
Here is the code in the GameScene: (empty but it was the menu before simplification)
import SpriteKit
class GameScene: SKScene {
var viewController:GameViewController?
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
viewController?.presentPlayScene()
}
}
Here is the code in the PlayScene:
import SpriteKit
let PlayerCategory: UInt32 = 1 << 2
let ObstacleCategory: UInt32 = 1 << 3
class PlayScene: SKScene, SKPhysicsContactDelegate {
let world = SKNode()
var player : SKShapeNode!
var firsttap = true
var viewController : GameViewController?
override func didMoveToView(view: SKView) {
physicsWorld.gravity = CGVectorMake(0.0, -9.8)
physicsWorld.contactDelegate = self
self.createPlayer()
let obstacle = SKSpriteNode(color: SKColor.whiteColor(), size: CGSizeMake(100.0, 38.0))
obstacle.position = CGPointMake(frame.size.width / 2.0, CGRectGetMidY(frame) * 0.75 + 400)
let body = SKPhysicsBody(rectangleOfSize: obstacle.size)
body.categoryBitMask = ObstacleCategory
body.contactTestBitMask = PlayerCategory
body.collisionBitMask = PlayerCategory
body.linearDamping = 0.0
body.angularDamping = 0.0
body.dynamic = false
obstacle.physicsBody = body
self.addChild(world)
self.world.addChild(obstacle)
self.world.addChild(player)
}
func createPlayer() {
self.player = SKShapeNode(circleOfRadius: 13)
player.fillColor = SKColor.greenColor()
player.strokeColor = SKColor.blackColor()
player.lineWidth = 1
let body = SKPhysicsBody(circleOfRadius:13)
body.dynamic = false
body.linearDamping = 0.0
body.angularDamping = 0.0
body.allowsRotation = false
body.affectedByGravity = true
body.categoryBitMask = PlayerCategory
body.contactTestBitMask = ObstacleCategory
body.collisionBitMask = ObstacleCategory
player.physicsBody = body
player.position = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame) * 0.75)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
for touch: AnyObject in touches {
if firsttap {
player.physicsBody?.dynamic = true
firsttap = false
}
let touchLoc = touch.locationInNode(self)
var right = true
if touchLoc.x > CGRectGetMidX(frame) {
right = false
}
player.physicsBody?.velocity = right ?
CGVectorMake(CGFloat(-65), CGFloat(650)) :
CGVectorMake(CGFloat(65), CGFloat(650))
}
}
override func update(currentTime: NSTimeInterval) {
var pos = -player.position.y + CGRectGetMidY(frame)
if pos < world.position.y {
world.position = CGPointMake(world.position.x, pos)
}
}
func didBeginContact(contact: SKPhysicsContact) {
viewController?.presentGameScene()
}
}
Here is the code in the gameViewController:
extension SKNode {
class func unarchiveFromFile(file : NSString) -> SKNode? {
if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
var sceneData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)
var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData!)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
if file == "GameScene"{
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as GameScene
archiver.finishDecoding()
return scene
}
else {
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as PlayScene
archiver.finishDecoding()
return scene
}
} else {
return nil
}
}
}
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.presentGameScene()
}
func presentPlayScene() {
if let scene = PlayScene.unarchiveFromFile("PlayScene") as? PlayScene {
// Configure the view.
let skView = self.view as SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
//reference to self
scene.viewController = self
skView.presentScene(scene, transition: SKTransition.crossFadeWithDuration(0.5))
}
}
func presentGameScene() {
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
// Configure the view.
let skView = self.view as SKView
skView.showsFPS = true
skView.showsNodeCount = true
skView.showsQuadCount = true
skView.showsDrawCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
//reference to self
scene.viewController = self
skView.presentScene(scene, transition: SKTransition.crossFadeWithDuration(0.5))
}
}
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> Int {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
} else {
return Int(UIInterfaceOrientationMask.All.rawValue)
}
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
Note: on iPhone 6 there is a very small lagging when quickly tapping on the screen at the very first beginning of the game.
I have replaced the SKShapeNode by SKSpriteNode and it hasn't changed anything.
Please help me, thank you so much in advance!