为什么创建大量SKNode需要这么长时间

时间:2016-11-06 12:49:32

标签: ios swift sprite-kit

我正在使用SpriteKit在Swift中为我的iOS App创建一个随机项微调器,但是目前我的方法效率不高,而且我几乎可以肯定它不是实现我的目标的最佳方式。我目前遵循的过程基本上是 - 在场景加载时,循环显示13个不同项目的列表(存储在JSON中)
- 创建一组显示相关数据的节点 - 将每组节点添加到第二组节点,沿x轴稍微移动每个节点,创建一长串SKNode(用于微调器的项目)
- 沿x轴移动该组,以给人一种旋转项目的印象

但是这个方法大约需要6秒才能加载场景(延迟是将节点添加到更大的节点:group.addChild(spinnerItem)而且我只是Swift的新手我确信有更好的方法我这样做,所以任何帮助/建议都会欣赏改进这个代码,因为它非常需要提高效率!

这是didMove函数......

override func didMove(to view: SKView) {
    var xPos = CGFloat(self.frame.width + 150)
    var eventWeapon = weapon()

    for n in 0...13{
        eventWeapon = getWeapon(caseName: "chromaCase", weaponID: n)
        print(eventWeapon)
        let texture = createSpinnerItem(wName: "\(eventWeapon.name)", wSkin: "\(eventWeapon.skin)", wColor: "\(eventWeapon.color)")
        let spinnerItem = SKSpriteNode(texture: texture)
        spinnerItem.position = CGPoint(x: xPos, y: self.frame.height / 2)
        group.addChild(spinnerItem)

        xPos = xPos + 300 * 1.2
    }

    self.addChild(group)
    group.run(SKAction.moveBy(x: -5000, y: 0, duration: 2))
}

和{...}中使用的createSpinnerItem函数。

func createSpinnerItem(wName: String, wSkin: String, wColor: String) -> SKTexture {
    let object = SKNode()

    let bGround = SKShapeNode(rectOf: CGSize(width: 300, height: 300))
    bGround.fillColor = color.offWhite
    bGround.strokeColor = color.gray
    bGround.lineWidth = 5
    object.addChild(bGround)

    let titleBG = SKShapeNode(rectOf: CGSize(width: 300, height: 100))
    if wColor == "blue"{ titleBG.fillColor = color.CSGOblue }
    if wColor == "red"{ titleBG.fillColor = color.CSGOred }
    if wColor == "pink"{ titleBG.fillColor = color.CSGOpink }
    if wColor == "purple"{ titleBG.fillColor = color.CSGOpurple }
    titleBG.strokeColor = color.gray
    titleBG.lineWidth = 5
    titleBG.position = CGPoint(x: 0, y: -150 + 50)
    object.addChild(titleBG)

    let weaponName = SKLabelNode()
    weaponName.text = wName
    weaponName.fontColor = color.white
    weaponName.fontSize = 40
    weaponName.fontName = "Avenir-Regular"
    weaponName.verticalAlignmentMode = .center
    weaponName.position = CGPoint(x: 0, y: -150 + 70)
    object.addChild(weaponName)

    let weaponSkin = SKLabelNode()
    weaponSkin.text = wSkin
    weaponSkin.fontColor = color.white
    weaponSkin.fontSize = 20
    weaponSkin.fontName = "Avenir-Regular"
    weaponSkin.verticalAlignmentMode = .center
    weaponSkin.position = CGPoint(x: 0, y: -150 + 30)
    object.addChild(weaponSkin)

    return object
}

1 个答案:

答案 0 :(得分:2)

您要做的第一件事就是确定您的感知是否"延迟是真实与否只是启动应用程序的开销。 6秒是一段很长的时间,所以如果没有测量,你就不会知道你是在夸大或理解真正的延迟。我会通过几个人的意识来理解我的意思。你应该按照KnightOfDragon的建议来实际测量时间。

我现在确实看到了代码的一个问题,并且我在人们使用SK上的代码看到的内容并不少见。这进入了上面提到的感知概念。处理工作所需的实际CPU使用率可能不会很大,但是您在运行时遇到的可能与实际预期的CPU负载不匹配。为什么?你可能在主线程上做了很多工作。从加载JSON到可能创建纹理。因此,你会发现通过使主线程挨饿,你可以看到你不会看到的减速。广义问题,应用程序或游戏,我看到许多人尝试在字面上加载didMove或app viewDidLoad中的所有内容。你真正想要做的就是把它当作引导起点。做最少量的工作来设置,然后使用你喜欢的方法异步调度耗时的东西。这样可以减轻你在执行文件I / O等操作时锁定主线程的问题。

是的,这确实使您的代码复杂化以便能够处理此问题,但这种做法并非典型。大多数引擎都有加载系统来帮助在后台加载项目并在完成后通知。在发生加载时,您通常会看到加载屏幕或其他指示。

请记住,当您修改SKNode层次结构时,您需要确保在正确的线程上执行此操作(例如,当您addChild到活动场景时)。您可以通过SKAction或主线程来完成。否则你的应用会崩溃。