SpriteKit游戏中的高CPU和帧速率下降

时间:2016-09-02 16:55:46

标签: swift xcode sprite-kit instruments

我正在用SpriteKit制作我的第一个游戏,其中敌人从一侧进入屏幕并从另一侧的屏幕上移开。我注意到在游戏后期,当呈现不同类型的敌人时,FPS下降并且CPU使用率接近100%(~95-99%)。我已经使用了两种仪器调试工具来获得这些结果:

在时间分析器工具中,我发现main我认为是appDelegate的主体是问题..我知道这看起来很明显,但我很惊讶看到这些功能像update中的GameScene几乎不是问题。有没有办法深入研究这个?如果这是导致问题的我的一个功能,我觉得好像更容易评估我搞砸了。

enter image description here 我还使用了分配工具,发现大量使用内存将构建新的外星精灵:

enter image description here

这是我添加普通外星人的代码:

func addNormAlien(){

    let mult = normAlienMultiplers

    let alienInst = normAlien(startPos:CGPoint(x: 10,y: 10), speed: random(UInt32(10),max: UInt32(50))*mult[0])

    let yStart = random(UInt32(alienInst.size.height/2), max: UInt32(size.height-alienInst.size.height))
    alienInst.position = CGPoint(x:size.width+alienInst.size.width/2, y:CGFloat(yStart))

    addChild(alienInst)
    totalNodes+=1
}

这是否有点预期,因为保持实例化新精灵的成本很高(即使我很少一次超过20)?我这样做只是为了确保它们的随机传播。

我还没有找到很多纹理尺寸 - 是否有一个惯例?目前,我发现自己使精灵纹理相当大,然后用setScale缩小它们而不是在图像编辑器中缩小它们。

我的GameScene文件开头的这些纹理和动画也是(预加载?),其中的行如

let laserTexture = SKTextureAtlas(named:"Sprites").textureNamed("laserTexture")`

let shipFrames = ["ship0","ship1","ship2","ship3","ship4","ship5","ship6","ship7","ship8","ship9","ship9","ship9","ship8","ship7","ship6","ship5","ship4","ship3","ship2","ship1","ship0"].map{textureAtlas.textureNamed($0)}`

之前:class GameScene: SKScene, SKPhysicsContactDelegate {

因此可以从我的Sprite类访问,如:

    super.init(texture: shipStartTexture, color: UIColor.clearColor(), size: shipStartTexture.size())

func animateShip1() {
    let animate = SKAction.animateWithTextures(shipFrames, timePerFrame: 0.1)
    let forever = SKAction.repeatActionForever(animate)
    self.runAction(forever)
}

如果有一种更好的预分配纹理的方法,我很乐意知道,并且如何进一步了解如何评估其他一些问题将会非常棒!

1 个答案:

答案 0 :(得分:2)

通常,您会发现main包含最高的CPU使用率,因为大多数情况都是从主线程运行的。您将需要向下钻取以找到您已经完成的实际违规者。请记住,这一切都是相对于您使用仪器的运行完成的。因此,如果您没有足够的数据点,您可以获得红色鲱鱼。一个例子是游戏加载。这可能是一项昂贵的操作。在某些情况下,它可能看起来相对较快(比如加载1-5秒),但是当你查看你的分析时,你可能会发现它消耗了大量的时间。但是,如果您在运行时发现FPS很高,那么该负载的开销是值得的。

转到您的方案,一个问题是您运行了多长时间?另一个是addNormAlien实际调用的频率是多少?是每一帧吗?你的addNormAlien有2个部分正在耗费时间,这是创建以及添加到层次结构。在不知道Apple如何实现这些项目的情况下,它们实际上是一个黑盒子,但很明显有些方面的创建是昂贵的。同样,不知道你的游戏的时间质量使得这很难完全固定下来。回到我前面提到的,如果所有这些工作都是在加载过程中完成的,那么这些数字可能是一个红色的鲱鱼。因此,您需要确保您的测试运行具有足够的代表性。

一个建议是创建已构建的外星人节点的现有池。然后在需要时从池中拉出一个对象(顺便说一下,你可能也应该包括你的normAlien方法)。这是BTW,它有多少游戏。他们根据使用加载时间产生"惩罚的前提,在运行时创建他们将需要的预分配版本的项目。对象创建,保持运行时相对没有开销。请注意,这有一个技巧。从池中提取空闲对象时,您需要进行一些最小化初始化。以前你一直在依赖构造函数/初始化程序。但由于这是一个已经创建的对象,你将不会有这种奢侈(记住你在尝试去除运行时不必要的开销)。这意味着你需要对它保持警惕,因为它可能会产生一些难以追踪的错误。

另一件事,我在你发布的其他帖子中提到的就是禁用内容。例如,发生了一个runAction,副本看起来很昂贵。

关于纹理大小。大到多大?一般来说,这是一个坏主意。这样做你会受到处罚。但是,根据大的大小,缩放比例等,开销可以忽略不计。一个简单的测试是运行一个版本,其中纹理是正确的大小而不是大的。如果你总是按比例缩小,没有理由使用大的。

无论如何,这里有很多东西需要研究,这就是为什么游戏性能调整可能很棘手,以及为什么一种游戏的方法可能不适用于另一种游戏。只有你知道你如何建立它的细微差别。

添加了基于信息的问题更新。

关于您对问题的更新。在我看来,你现在正在扩大范围到不相关的项目(预加载纹理),并且还在寻找一个银弹或一站式解答你所有的困境。空无一人。如上所述,补救这些类型的东西可能是棘手的,并且高度依赖游戏。只有你知道你的游戏,只有你可以在乐器中运行它。有一种策略可供使用。其中很大一部分来自经验和一些问题(例如,为什么初始化需要这么长时间?)。如果这导致更多的SO问题,那么就可以解决问题。

关于预加载纹理,您需要为此创建一个新问题。想想你在很多游戏中看到的加载屏幕。为什么你认为他们存在?在背景中加载像纹理和其他数据的东西。是的,它增加了开发复杂性,但需要为用户提供更好的体验。预加载是通过preload完成的。您在代码片段中引用的内容只是数据的初始化,以后可以用它来引用纹理实例。

我建议你做的是找到隔离部分代码的方法,以确定你的性能影响来自哪里。例如,您已检查节点计数。 20不是很大。 PI会令人惊讶的是,动态创建它们会产生这样的开销,但是你的时间分析确实表明可能会有一些重大的开销。如果init开销确实很大,你可以通过简单地让你的游戏每帧都分配新的外星人来测量它。您应该可以运行几秒钟而不会耗尽内存。然后,您可以使用它来开始删除部分代码,以查看它对性能的影响。你应该在这里看到,这很多都会成为试验和错误。没有银弹/设定答案,需要一定的心态才能善于优化。

我在其他一个问题中提到了这一点,但如果你在模拟器上这样做,那么调整性能并不是正确的方法。必须在设备上完成。