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

You*_*wad 1 performance ios sprite-kit sknode swift

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

所以我想知道是否值得使用计时器(以 1/60 时间间隔重复)来向我的自定义 SKNode 添加自定义更新(甚至可能是一个将其添加到所有 SKNode 的扩展)。然而,我想这将是相当内存密集型的。所以我想问是否有一些关于此的“最佳实践”。如果计时器在每一帧上触发而不是强制每秒触发 60 次,也许计时器会起作用。

Luc*_*tti 6

绝对不要使用计时器。

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

如果您确实想在节点内编写更新逻辑,那么最好的解决方案是创建您自己的update方法,然后从GameScene.

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

协议

protocol Updatable: class {
    func update(currentTime: NSTimeInterval)
}
Run Code Online (Sandbox Code Playgroud)

使你的精灵/节点可更新

class Player: SKSpriteNode, Updatable {

    func update(currentTime: NSTimeInterval) {
        // your logic goes here
    }
}
Run Code Online (Sandbox Code Playgroud)

将更新从场景转发到节点

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) }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我正在使用Updatables. 当将新元素添加(或删除)到场景图中时,您还应该注意Updatables向数组中添加(或删除)新元素。

虽然绝对可以每帧搜索整个场景图,但从性能角度来看,这会非常糟糕。

这是正确的方法吗?

SKNode就我个人而言,我不喜欢在or的子类中编写这种代码SKSpriteNode

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

  1. gameStarted
  2. touchesBegan
  3. touchesEnded

该类包含游戏的纯游戏逻辑。

它就像您可以在棋盘游戏中找到的说明手册一样,并且与游戏实体的图形表示完全无关。

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

  • @YoussefSami 搜索所有“Updatables”是安全的 __BUT__ 有两个巨大的缺点。__1)__ 从性能的角度来看,这是非常糟糕的。这意味着您正在通过场景图执行搜索的每一帧。它非常昂贵,并且像我向您展示的那样缓存此列表会更好。__2)__ 请记住,某些“Updatables”不能是“GameScene”的直接子级。它们可能是“GameScene”的子级的子级。所以这不是一个简单的事情。这是对场景图的完整访问。 (2认同)