Ralentissements sur un tutoriel SpriteKit

heliohelio Membre

Salut à tous,
J'ai voulu utiliser à nouveau un peu SpriteKit, j'ai suivi le tuto suivant :
https://github.com/twostraws/HackingWithSwift/blob/master/Classic/project36/Project36/GameScene.swift
c'est un clone de Flappy Bird, cependant je note des ralentissements dans le jeu. En effet à chaque fois que des nouveaux rochers se créent, il y un ralentissement.
ça concerne cette partie :

func createRocks() {
    // 1
    let rockTexture = SKTexture(imageNamed: "rock")

    let topRock = SKSpriteNode(texture: rockTexture)
    topRock.physicsBody = SKPhysicsBody(texture: rockTexture, size: rockTexture.size())
    topRock.physicsBody?.isDynamic = false
    topRock.zRotation = .pi
    topRock.xScale = -1.0

    let bottomRock = SKSpriteNode(texture: rockTexture)
    bottomRock.physicsBody = SKPhysicsBody(texture: rockTexture, size: rockTexture.size())
    bottomRock.physicsBody?.isDynamic = false
    topRock.zPosition = -20
    bottomRock.zPosition = -20


    // 2
    let rockCollision = SKSpriteNode(color: UIColor.red, size: CGSize(width: 32, height: frame.height))
    rockCollision.physicsBody = SKPhysicsBody(rectangleOf: rockCollision.size)
    rockCollision.physicsBody?.isDynamic = false
    rockCollision.name = "scoreDetect"

    addChild(topRock)
    addChild(bottomRock)
    addChild(rockCollision)


    // 3
    let xPosition = frame.width + topRock.frame.width

    let max = CGFloat(frame.height / 3)
    let yPosition = CGFloat.random(in: -50...max)

    // this next value affects the width of the gap between rocks
    // make it smaller to make your game harder – if you're feeling evil!
    let rockDistance: CGFloat = 70

    // 4
    topRock.position = CGPoint(x: xPosition, y: yPosition + topRock.size.height + rockDistance)
    bottomRock.position = CGPoint(x: xPosition, y: yPosition - rockDistance)
    rockCollision.position = CGPoint(x: xPosition + (rockCollision.size.width * 2), y: frame.midY)

    let endPosition = frame.width + (topRock.frame.width * 2)

    let moveAction = SKAction.moveBy(x: -endPosition, y: 0, duration: 6.2)
    let moveSequence = SKAction.sequence([moveAction, SKAction.removeFromParent()])
    topRock.run(moveSequence)
    bottomRock.run(moveSequence)
    rockCollision.run(moveSequence)
}

func startRocks() {
    let create = SKAction.run { [unowned self] in
        self.createRocks()
    }

    let wait = SKAction.wait(forDuration: 3)
    let sequence = SKAction.sequence([create, wait])
    let repeatForever = SKAction.repeatForever(sequence)

    run(repeatForever)
} 

J'ai déplacé l'instruction :

let rockTexture = SKTexture(imageNamed: "rock")

pour ne pas qu'elle soit recréé à chaque fois dans createRocks mais rien n'y fait.

Vous auriez une idée ?
Merci.

Mots clés:

Réponses

  • DrakenDraken Membre

    Ralentissement sur device, ou avec un simulateur iOS ?

  • heliohelio Membre
    Sur les 2 !
    Et ça se passe apparemment lorsque les rochers suivants sont créés. Les précédents ne sont pas supprimés assez tôt ! Mais ça me parait étonnant, dans certains jeux il me semble qu’il y a un paquet de nodes en même temps !
  • DrakenDraken Membre

    Sans plus d'informations sur le sujet, je te suggère de faire un mécanisme de recyclage. Au lieu de détruire les rochers, tu les stockes dans un tableau pour réutilisation ultérieur. Cela évite les cycles de destruction/reconstruction coûteux en ressources mémoire.

  • heliohelio Membre

    OK merci

  • CéroceCéroce Membre, Modérateur

    J'ai juste lancé sur le simu pour essayer.
    Effectivement, je ne peux pas te dire pourquoi ajouter ces nodes à la scène est si lent.

    J'ai déplacé l'instruction :
    let rockTexture = SKTexture(imageNamed: "rock")
    pour ne pas qu'elle soit recréé à chaque fois dans createRocks mais rien n'y fait.

    Ça ne m'étonne pas, je pense qu'il y a un cache pour les images.

    Mon réflexe serait de mesurer dans Instruments pour en savoir plus (je n'ai pas pu, n'ayant pas de compte perso).

    La solution de Draken me semble judicieuse mais pas maintenant. Je veux dire, ça peut représenter beaucoup de travail alors qu'on ne sait pas quel est le problème réel.
    Paul Hudson ne parle pas de ce problème dans la suite du tuto ?

  • heliohelio Membre
    28 avril modifié #7

    Etonnamment, sur stackoverflow Paul Hudson dit lui meme, dans un post ouvert par une personne qui présente le même problème que moi, qu'il n'a aucun lag !
    https://stackoverflow.com/questions/34256484/swift-game-lags-when-creating-spritenodes

  • DrakenDraken Membre
    29 avril modifié #8

    @helio a dit :
    Etonnamment, sur stackoverflow Paul Hudson dit lui meme, dans un post ouvert par une personne qui présente le même problème que moi, qu'il n'a aucun lag !

    Le problème est peut-être récent, du à un changement (ou un bug) dans le moteur de SpriteKit. Parce que c'est difficile à rater .. sur mon iPad Pro le frame rate passe de 60 fps à 55 fps pendant au moins 0,3 s à chaque apparition d'un pic rocheux. C'est encore pire sur le simulateur, avec une chute à 46 fps !

    Le système de collision est juste horrible .. Utiliser une forme rectangulaire pour gérer la collision avec un objet rocher fin et allongé, c'est n'importe quoi.

    J'ai fait une copie d'écran avec visualisation des zones de collisions. C'est complètement injouable ce truc. En bas de l'écran, la zone rectangulaire de collision fait 4x le volume du pic rocheux ..

    La zone géométrique de collision doit suivre (approximativement) la forme de l'objet, sinon c'est ridicule. D'ailleurs, vu le faible nombre d'objets le corps physique peut être généré directement en pixel-perfect à partir de la texture, pour une collision vraiment précise.

Connectez-vous ou Inscrivez-vous pour répondre.