在场景的update()之外更新SKNodes

时间:2016-07-10 19:22:18

标签: ios swift performance sprite-kit sknode

我很惊讶SKScene类中的更新方法实际上并未从SKNode继承。对我而言,所有SKNode能够自我更新似乎是合乎逻辑的(例如,当它不再显示时,将其自身从场景中移除)等等。我认为这有助于使实例分离独立实体(没有依赖性,没有意外行为)如果仅在场景中保留更新背后有其他逻辑,请解释。

所以我想知道是否值得使用计时器(以1/60时间间隔重复)为我的自定义SKNode添加自定义更新(甚至可能是一个将此添加到所有人的扩展程序) SKNodes)。但是,我想这将是非常耗费内存的。所以我想问一下是否有一些最好的做法'对此。如果计时器在每一帧发射而不是每秒发射60次,那么计时器可能会起作用。

1 个答案:

答案 0 :(得分:1)

绝对不要使用计时器。

SpriteKit有一个定义明确的更新周期,每种更新(逻辑,物理,图形)都应该在明确定义的时间范围内发生。

如果您真的想在节点内编写更新逻辑,那么最好的解决方案是创建自己的update方法,然后从GameScene手动调用它。

让我们看一下(可能的)结构化方法

协议

protocol Updatable: class {
    func update(currentTime: NSTimeInterval)
}

使您的精灵/节点可更新

class Player: SKSpriteNode, Updatable {

    func update(currentTime: NSTimeInterval) {
        // your logic goes here
    }
}

将更新从场景转发到节点

class GameScene: SKScene {

    private var updatables = [Updatable]()

    override func didMoveToView(view: SKView) {
        let player = Player()
        updatables.append(player)
        self.addChild(player)
    }

    override func update(currentTime: NSTimeInterval) {
        updatables.forEach { $0.update(currentTime) }
    }
}
  

如您所见,我正在使用Updatables数组。在将新的Updatables添加(或删除)到场景图中时,您还应该注意添加(或删除)新的SKNode

     

虽然从每一帧搜索整个场景图肯定是可能的,但从性能的角度来看,它会非常糟糕。

这是正确的方法吗?

我个人不喜欢在SKSpriteNodeLogic的子类中编写这种代码。

我通常会创建一个update类。此类是从GameScene接收gameStarted事件的类。它还接收其他“逻辑事件”,如:

  1. touchesBegan
  2. touchesEnded
  3. Logic
  4. 此课程包含游戏的纯游戏逻辑

    您可以在棋盘游戏中找到类似使用说明书的内容,而且它完全不了解游戏实体的图形表示。

    在理想情况下,我可以从我的SpriteKit游戏中提取getElementsByClassName()类,并将其与其他框架一起使用,甚至与同一游戏的(非电子)棋盘游戏版本一起使用。