简体   繁体   English

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

[英]Updating SKNodes outside update() of scene

I was quite surprised that the update method in the SKScene class isn't actually inherited from SKNode. 我很惊讶SKScene类中的update方法实际上没有继承自SKNode。 To me, it seems logical for all SKNodes to be able to update themselves (for instance to remove itself from the scene when it's no longer on display, among other things). 对我来说,所有SKNode都能够进行更新似乎是合乎逻辑的(例如,在不再显示时将其从场景中删除)。 I think this would help in making the instances separate independent entities (no dependencies, no unexpected behavior) If there is other logic behind keeping the updates in the scenes only, please explain. 我认为这将有助于使实例分离为独立实体(没有依赖关系,没有意外行为)。如果仅在场景中保留更新,还有其他逻辑,请解释。

So I'm wondering if it's worth using a timer (repeating with a 1/60 time interval) to add a custom update to my custom SKNodes (perhaps even an extension that will add this to all SKNodes). 所以我想知道是否值得使用计时器(以1/60的时间间隔重复)向我的自定义SKNode添加自定义更新(甚至可能是将其添加到所有SKNode的扩展)。 However, I imagine this will be quite memory intensive. 但是,我想这会占用大量内存。 So I would like to ask if there is some 'best practice' regarding this. 因此,我想问一下是否有“最佳实践”。 Perhaps the timer would work if it fired at each frame rather forcing it to fire 60 times a second. 如果计时器在每个帧处触发,而不是强制它每秒触发60次,则可能会起作用。

Absolutely DO NOT use a timer. 绝对不要使用计时器。

SpriteKit has a well defined update cycle and every kind of update (logic, physics, graphics) should happen into a well defined time frame. SpriteKit具有明确定义的更新周期,每种更新(逻辑,物理,图形)都应在明确定义的时间范围内进行。

If you really want to write the update logic inside your nodes then the best solution is creating your own update method and then manually invoking it from the GameScene . 如果您真的想在节点内部编写更新逻辑,那么最好的解决方案是创建自己的update方法,然后从GameScene手动调用它。

Let's see a (possible) structured approach 让我们看一个(可能的)结构化方法

The protocol 协议

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

Making your sprite/node updatable 使您的精灵/节点可更新

class Player: SKSpriteNode, Updatable {

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

Forwarding the updates from the scene to the nodes 将更新从场景转发到节点

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

As you can see I am using an Array of Updatables . 如您所见,我正在使用Updatables数组。 You should also take care of adding (or removing) new Updatables to the Array when they are added (or removed) to the scene graph. 当将新的Updatables表添加(或删除)到场景图中时,还应注意将新的Updatables表添加(或删除)到数组。

While it's definitely possible searching the whole scene graph every frame it would be very bad by a performance point of view. 虽然绝对有可能在每一帧中搜索整个场景图,但从性能的角度来看这将是非常糟糕的。

Is this the right way to go? 这是正确的方法吗?

Personally I don't like writing this kind of code inside my subclasses of SKNode or SKSpriteNode . 我个人不喜欢在我的SKNodeSKSpriteNode子类中编写这种代码。

I usually create a Logic class. 我通常创建一个Logic类。 This class is the ones that receives the update events from GameScene. 此类是从GameScene接收update事件的类。 It also receives other "logic events" like: 它还接收其他“逻辑事件”,例如:

  1. gameStarted
  2. touchesBegan
  3. touchesEnded

This class contains the pure game logic of the game. 此类包含游戏纯粹游戏逻辑

It is something like the Instruction Manual you can find into a board game and it is totally agnostic about the graphics representation of the game entities. 就像在棋盘游戏中可以找到的《 使用手册》一样,它完全与游戏实体的图形表示无关。

In an ideal scenario I would be able to extract the Logic class from my SpriteKit game and use it with another framework or even with a (non electronic) board game version of the same game. 在理想情况下,我将能够从我的SpriteKit游戏中提取Logic类,并将其与其他框架甚至同一游戏的(非电子)棋盘游戏版本一起使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM