【问题标题】:SpriteKit SKAction doesn't work after removing and readding a node删除和读取节点后,SpriteKit SKAction 不起作用
【发布时间】:2013-10-31 17:30:28
【问题描述】:

我已经为此纠结了一天,我真的不知道发生了什么。

我有一个非常简单的设置:一个 SKNode(我们称之为基),它包含另一个 SKNode(子基),以及几个 SKShapeNode 对象。有时,我将 SKShapeNode 对象之一(使用 removeFromParent)从基础节点移动到子基础节点。然后我应用一个 SKAction,它将节点移动到某个任意位置。

除了,当 SKShapeNode 已被移除并添加到子基础对象时,SKAction 不起作用。如果我将它从底座中取出,然后放回底座中,SKActions 将再次起作用。

我完全被难住了。当节点添加到另一个节点时,是否有一些属性在节点上设置,当我删除它时没有正确重置......?我无法想象这是应该发生的事情。

非常欢迎任何想法。

更新:

这是一些我可以用来生成它的代码。该函数位于 SKNode 的子类中。该类添加了一堆 SKShapeNode,它还有另一个名为 testNode 的 SKNode,所以,废话不多说:

-(void) removeThenAdd
{
    [someNode removeFromParent];

    [self.testNode addChild:someNode];

    SKAction* action = [SKAction moveTo:CGPointMake(200, 200) duration:1];

    SKNode* thatSameNodeJustAdded = [self.testNode.children objectAtIndex:0];

    [thatSameNodeJustAdded runAction:action];
}

另一个更新!

我刚刚发现,如果我在该节点位于 testNode 内时向该节点添加一个 SKAction,然后将其从 testNode 中删除并将其添加回其原始父级,则该操作将被激活。就像,我在这里错过了什么?这一定是我没有正确使用的某种设计行为..

【问题讨论】:

  • 显示传输代码和您运行的操作。我可以想象移动动作是使用节点的原始位置(和父坐标空间)初始化的,并且在您“重新设置”节点时不会更新它们的目标目的地。
  • 我正在重新创建动作,在某些情况下,在节点重新设置父节点之后很久,所以我猜不可能是这样?无论如何,我放了一些代码。
  • 当您说“它不起作用”时,您需要更加具体。你有错误吗?它不会像你期望的那样移动?如果是这样,请告诉我们它到底做了什么,以便我们可以利用这些信息。听起来这可能是关于您使用 MoveTo 并且不期望 SKNode 以不同的方式工作,因为它现在有一个新的坐标空间。 200,200 与原始母公司,可能与新母公司的全球位置不同。如果可以,请说得更具体。
  • 是的,我希望我能更具体一些。但实际上什么也没发生。我在代码周围放置了日志,所以我可以看到它正在运行它,我没有收到任何错误,如果我在孩子回到父节点(已经移动到另一个 SKNode 并返回)时执行相同的操作,它工作正常。我选择 200,200 是因为它在移动很明显,因为它位于 testNode 对象中的 0,0 处。它根本不动。有没有办法调试 SKActions 的内部工作......?
  • 你确定同一个节点在 children 数组的索引 0 处吗?

标签: ios objective-c sprite-kit


【解决方案1】:

这似乎是 SDK 中的一个错误。我遇到了这个问题,因为我想在他们自己的场景文件中制作高级精灵(带有孩子、发射器等的精灵),这样我就可以有选择地加载它们,然后将它们添加到我的场景中。我想出了一个使用 NSKeyedArchiver 和 NSKeyedUnarchiver 的解决方法——将节点(或父节点)转换为数据,然后再返回,如果它是发射器或有子对象,则新对象已准备好添加到场景中作为发射器的节点,它们都将被复制并正确地重新添加。这是我为 swift 制作的扩展,就像一个魅力:

extension SKNode {
    // Pulling a node from one scene and putting it into another causes some problems with broken emitters :(
    // Fix here is to archive and then unarchive the node before returning
    class func nodeFromScene(nodeName : String, sceneFileName : String) -> SKNode? {
        if let scene = SKScene(fileNamed: sceneFileName), node = scene.childNodeWithName(nodeName) {
            let archive = NSKeyedArchiver.archivedDataWithRootObject(node)
            return NSKeyedUnarchiver.unarchiveObjectWithData(archive) as? SKNode
        }
        return nil
    }
}

【讨论】:

    【解决方案2】:

    我在我的 SpriteKit 项目中也看到了这个问题。在我的例子中,我从场景编辑器中创建的 SKScene 文件中删除了一个节点,并将其添加到我当前的场景中。

    在进行了一些调试后,它显示这些操作根本没有运行。经过进一步调查,我发现了原因……似乎当您以这种方式向场景添加节点时,isPaused 属性设置为true。这是故意的还是我无法确定的错误。

    来自文档: https://developer.apple.com/documentation/spritekit/sknode/1483113-ispaused

    暂停

    如果值为 true,则在场景处理动作时跳过节点(及其所有后代)。

    所以为了“修复”这个问题,在节点上运行任何 SKActions 之前,取消暂停节点:

    node.isPaused = false
    

    【讨论】:

      猜你喜欢
      • 2019-11-07
      • 1970-01-01
      • 2014-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-13
      相关资源
      最近更新 更多