【问题标题】:FPS drops and game slows down - Sprite-Kit and SwiftFPS 下降和游戏变慢 - Sprite-Kit 和 Swift
【发布时间】:2015-01-06 18:26:32
【问题描述】:

我有一个使用 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)
}

【问题讨论】:

  • 您是否在游戏中使用了多个 UIVIewController?根据以前的经验,这会导致性能非常差。
  • 节点计数仅考虑正在绘制的节点。屏幕外节点不计算在内,但仍可能在层次结构中。但是因为它们没有被绘制。无论如何,这可能有很多原因,并且需要一些您至少怀疑或更好的代码:已经衡量表现不佳。一个非常常见的初学者错误是创建过多的节点或实体,可能每次都应该改变某些东西,而不是仅仅改变它们的属性。但这是一个锅底。开始删除代码,直到发现性能明显更好,然后在此处发布该代码(具有性能影响)。
  • @LearnCocos2D 谢谢,我发布了一些我认为可能是问题的代码(当我生成下降的圆圈时它可能会减慢)
  • 你在哪里以及如何删除节点?如果您不知道,这不会自动发生。
  • @LearnCocos2D 我没有删除从屏幕上掉下来的圆圈的节点,我该怎么做?您认为这是问题所在吗?

标签: ios performance swift sprite-kit frame-rate


【解决方案1】:

可能存在内存泄漏。

  1. 使用 Xcode 启动您的游戏。
  2. 使用 CMD + 6 打开 Xcode Debug Navigator 面板。
  3. 选择内存,等待分配的内存是否增长。

如果发生这种情况,我的意思是如果分配的内存继续增长,即使你知道它不应该增长,那么你就是在泄漏内存。

Instruments 是找出代码中问题所在的最佳工具。

【讨论】:

    【解决方案2】:

    我以前有过这个,节点数看起来它们已经消失了,但实际上并没有。

    您需要从视图中删除圆圈才能真正摆脱它们。

    首先,您将定义一个集合(在您的类中,但不在任何函数中)

     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)
               }
          }
     }
    

    基本上这样做是,在每一帧,检查是否有任何圆圈低于屏幕底部,如果是,则删除它们。

    【讨论】:

      【解决方案3】:

      SKShapeNodeSKSpriteNode 相比性能更差,因此应尽量避免使用SKShapeNode

      From Apple's documentation:

      形状节点对于不易分解的内容很有用 变成简单的纹理精灵。形状节点对于 在游戏之上构建和显示调试信息 内容。但是,SKSpriteNode 类提供了更高的性能 比这个类,所以要谨慎使用形状节点。

      如果你真的想使用SKShapeNodes (也许是因为它很容易进行原型设计)我建议你这样做:

      • 一次为您的形状创建纹理,可能在加载场景时。
      • 缓存渲染的纹理。在您的情况下,具有大小和纹理的字典似乎是合适的,例如[CGSize: SKTexture].
      • 从那时起,只要您需要形状,就可以从缓存中检索纹理并使用SKSpriteNode 显示它们。

      SKShapeNode 渲染到纹理you can use SKView's textureFromNode function

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多