FPS降低并且游戏变慢 - Sprite-Kit和Swift

4
我有一个使用Sprite-Kit和Swift的游戏,在游戏中我会随机生成圆形从屏幕顶部落下到屏幕底部。
游戏一开始运行得很好(大约在60 FPS以下),但渐渐地FPS下降,游戏变得极慢... 我不明白为什么FPS会随着时间而下降(节点数量保持在8-10左右,所以它们离开屏幕后就被删除了) - 我在iOS模拟器和实际设备上都进行了测试,有什么想法吗?
我已经检查过,问题并不是来自内存泄漏。另外,我只使用一个视图控制器。
我认为可能导致这个问题的唯一函数是这个,但我不知道为什么:
/* Function to generate single random circle */
func generateCircle() -> Void {
    let circleSize:CGFloat = CGFloat(arc4random_uniform(40) + 3)
    let xPosition:CGFloat = CGFloat(arc4random_uniform(UInt32(size.width)))

    var randomCircle = SKShapeNode(circleOfRadius: circleSize)
    randomCircle.strokeColor = SKColor.redColor()
    randomCircle.fillColor = SKColor.redColor()
    randomCircle.physicsBody = SKPhysicsBody(circleOfRadius: circleSize)
    randomCircle.physicsBody?.dynamic = false
    randomCircle.position = CGPoint(x: xPosition, y: size.height + circleSize*2)
    randomCircle.physicsBody?.dynamic = true
    randomCircle.physicsBody?.categoryBitMask = randomCirclesGroup
    addChild(randomCircle)
}

你的游戏中可能使用了多个UIVIewControllers吗?根据以往经验,这会导致非常糟糕的性能。 - Bokoskokos
节点计数仅考虑正在绘制的节点。屏幕外的节点不计入计数,但可能仍在层次结构中。但由于它们没有被绘制,这可能有很多原因,并且需要一些代码来至少怀疑,或者更好的是:已经测量以执行不良。一个非常常见的初学者错误是创建太多的节点或主体,可能每次都要改变一些东西,而不是只改变它们的属性。但这只是一个猜测。开始删除代码,直到您发现性能明显更好,然后将具有性能影响的代码发布在此处。 - CodeSmile
@LearnCocos2D 谢谢,我已经发布了一些代码,我认为这可能是问题所在(当我生成下落的圆圈时,它可能会变慢)。 - sachalondon
@LearnCocos2D 是的,我明白了,但是我怎么知道一个圆形何时超出屏幕边界以便将其移除? - sachalondon
当场景框架和精灵框架的CGRectIntersectsRect不再返回true时。 - CodeSmile
显示剩余4条评论
3个回答

3
也许存在内存泄漏。
  1. 使用Xcode启动游戏。
  2. 使用CMD + 6打开Xcode调试导航器面板。
  3. 选择内存,等待看分配的内存是否增加。

如果发生这种情况,也就是说,即使您知道不应该增加分配的内存,它仍然继续增长,那么您就会出现内存泄漏。

而找到代码中问题所在的最佳工具是Instruments


1

我以前遇到过这个问题,节点计数让它看起来好像它们已经消失了,但实际上它们并没有。

你需要从视图中移除这些圆圈才能真正摆脱它们。

首先,你需要定义一个集合(在你的类内部,但不在任何函数内部)。

 let circles = Set<SKShapeNode>()

然后在generateCircle()函数中,你会这样说:

 circles.insert(randomCircle)

然后在update()函数中:
 override func update(currentTime: CFTimeInterval){
      for index in circles {
           if index.position.y <= 0 {
                index.removeFromParent()
                circles.remove(index)
           }
      }
 }

基本上,这个程序会在每一帧检查所有圆形是否低于屏幕底部,如果是,则删除它们。

0

SKShapeNode的性能比SKSpriteNode差,如果可能的话应该尽量避免使用SKShapeNode

来自苹果文档

形状节点适用于无法轻松分解为简单纹理精灵的内容。形状节点还非常适用于在游戏内容上构建和显示调试信息。但是,SKSpriteNode类比此类提供更高的性能,因此请谨慎使用形状节点。

如果您真的想使用SKShapeNode (可能因为它易于原型设计),我建议您执行以下操作:

  • 仅在场景加载时创建形状的纹理。
  • 缓存渲染的纹理。在您的情况下,似乎适合使用一个带有大小和纹理的字典,例如[CGSize: SKTexture]
  • 从那时起,每当您需要形状时,请从缓存中检索纹理,并使用SKSpriteNode显示它们。
要将一个SKShapeNode渲染成纹理你可以使用SKView的textureFromNode函数

渲染节点树的内容,并将渲染后的图像作为SpriteKit纹理返回。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接