Ios 在场景的update()外部更新节点

Ios 在场景的update()外部更新节点,ios,swift,performance,sprite-kit,sknode,Ios,Swift,Performance,Sprite Kit,Sknode,我很惊讶SKScene类中的update方法实际上不是从SKNode继承的。在我看来,所有SKNodes都能够自我更新似乎是合乎逻辑的(例如,当它不再显示时,从场景中移除自己,等等)。我认为这将有助于使实例独立于独立的实体(没有依赖关系,没有意外行为),如果有其他逻辑将更新仅保留在场景中,请解释 因此,我想知道是否值得使用计时器(以1/60的时间间隔重复)向我的自定义SKNodes添加自定义更新(甚至可能是将此添加到所有SKNodes的扩展)。然而,我想这将是相当内存密集型的。所以我想问一下,在

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

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

绝对不要使用计时器。 SpriteKit有一个明确定义的更新周期,每种更新(逻辑、物理、图形)都应该在明确定义的时间范围内进行

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

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

协议 使您的精灵/节点可更新 将更新从场景转发到节点 如您所见,我使用的是一个
可更新的数组
。在将新的
可更新内容添加(或删除)到场景图中时,还应注意将其添加(或删除)到数组中

虽然每一帧都可以搜索整个场景图,但从性能角度来看,这是非常糟糕的

走这条路对吗? 就个人而言,我不喜欢在
SKNode
SKSpriteNode
的子类中编写这种代码

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

  • gameStarted
  • 触摸开始
  • touchesend
  • 此类包含游戏的纯游戏逻辑

    它类似于你可以在棋盘游戏中找到的说明手册,对于游戏实体的图形表示完全不可知

    在理想的情况下,我可以从我的SpriteKit游戏中提取
    逻辑
    类,并将其用于另一个框架,甚至用于同一游戏的(非电子)棋盘游戏版本。

    绝对不要使用计时器。 SpriteKit有一个明确定义的更新周期,每种更新(逻辑、物理、图形)都应该在明确定义的时间范围内进行

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

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

    协议 使您的精灵/节点可更新 将更新从场景转发到节点 如您所见,我使用的是一个
    可更新的数组
    。在将新的
    可更新内容添加(或删除)到场景图中时,还应注意将其添加(或删除)到数组中

    虽然每一帧都可以搜索整个场景图,但从性能角度来看,这是非常糟糕的

    走这条路对吗? 就个人而言,我不喜欢在
    SKNode
    SKSpriteNode
    的子类中编写这种代码

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

  • gameStarted
  • 触摸开始
  • touchesend
  • 此类包含游戏的纯游戏逻辑

    它类似于你可以在棋盘游戏中找到的说明手册,对于游戏实体的图形表示完全不可知


    在理想情况下,我可以从SpriteKit游戏中提取
    逻辑
    类,并将其用于另一个框架,甚至用于同一游戏的(非电子)棋盘游戏版本。

    我几乎在提交问题时就想到了这一点。然而,我管理可更新内容的方法不同。我没有保留数组,而是遍历所有子节点并使用if-let检查节点是否是可更新的。这安全吗?@YoussefSami搜索所有的
    可更新内容是安全的,但是有两个巨大的缺点。1) 从性能的角度来看,这是非常糟糕的。这意味着在场景图中执行搜索的每一帧。这是非常昂贵的,它会更好地缓存这个列表,我给你看。2) 请记住,一些
    可更新内容
    不能是
    游戏场景
    的直接子项。他们可能是
    游戏场景
    的孩子的孩子。所以这不是一个简单的问题。这是对你的场景图的一次完整访问。我几乎在提交问题时就想到了这一点。然而,我管理可更新内容的方法不同。我没有保留数组,而是遍历所有子节点并使用if-let检查节点是否是可更新的。这安全吗?@YoussefSami搜索所有的
    可更新内容是安全的,但是有两个巨大的缺点。1) 从性能的角度来看,这是非常糟糕的。这意味着在场景图中执行搜索的每一帧。这是非常昂贵的,它会更好地缓存这个列表,我给你看。2) 请记住,一些
    可更新内容
    不能直接作为
    游戏的子项
    
    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) }
        }
    }