iOS SpriteKit SKAction完成调用不工作/创build奇怪的结果

我试图让一个SKNode移动到屏幕上的命令。 我build立了以下SKAction链,以便1)节点向上和向外移动,然后2)节点向下移动到起始位置,然后3)开始移动。 我用下面的代码来尝试和实现这个:

SKAction *moveUp = [SKAction moveTo: shipIntroSpot1 duration:3.0]; SKAction *moveDown = [SKAction moveTo:shipSpot1 duration:ship1MovementSpeed]; [self enumerateChildNodesWithName:@"ship1" usingBlock:^(SKNode *node, BOOL *stop) { NSLog(@"RUNNING MOVE UP"); [node runAction: moveUp]; [node runAction:moveUp completion:^{ NSLog(@"RUNNING MOVE DOWN"); [node setHidden: NO]; [node runAction: moveDown]; }]; [node runAction:moveDown completion:^{ NSLog(@"STARTING MOVEMENT"); }]; 

但是,SKActions似乎并没有按照正确的顺序开火。 我使用的代码,一旦一步完成,下一步将开始。 然而,在下一个SKAction开始工作之前,SKAction似乎没有足够快地移动节点。 我的印象是,使用完成调用将意味着下一个行动不会开始,直到前一个完成? 这似乎并不是这种情况。 另外,如果我为步骤1(MOVING UP)留下了足够长的时间,它将跳过步骤2(MOVING DOWN)并开始执行步骤3(STARTTING MOVEMENT)。 我完全不知道这是如何可能的。 如果有人可以指出我的错误理解如何正确链接不同的行动,我将不胜感激。

(我没有做SKAction序列,因为我必须在半途中“取消隐藏”节点,我不认为我可以把它放在一个序列中,除非我错了。)

这似乎并不像你理解如何执行runAction。

运用

  [node runAction:moveUp completion:^{ NSLog(@"RUNNING MOVE DOWN"); [node setHidden: NO]; [node runAction: moveDown]; }]; 

不只是在动作结束时定义一个完成,而是运行动作,然后调用完成,所以第一个[node runAction:moveUp]需要被删除。

其次,在一个函数/块中创build的两个runAction调用将被同时调用,并且由于您调用了[node runAction:moveUp],[node runAction:moveUp completion:]和[node runAction:moveDown completion:]同一块,他们将全部同时执行。

这是你正在寻找的代码:

 SKAction *moveUp = [SKAction moveTo: shipIntroSpot1 duration:3.0]; SKAction *moveDown = [SKAction moveTo:shipSpot1 duration:ship1MovementSpeed]; [self enumerateChildNodesWithName:@"ship1" usingBlock:^(SKNode *node, BOOL *stop) { NSLog(@"RUNNING MOVE UP"); [node runAction:moveUp completion:^{ NSLog(@"RUNNING MOVE DOWN"); [node setHidden: NO]; [node runAction:moveDown completion:^{ NSLog(@"STARTING MOVEMENT"); }]; }]; 

完成块在动作完成后运行。 所以,如果你想向上移动,然后向下移动,然后移动,你需要写下面的代码:

 [node runAction:moveUp completion:^{ [node runAction:moveDown completion:^{ NSLog(@"STARTING MOVEMENT"); }]; }]; 

你现在所拥有的将无法工作,因为你连续调用了三个runAction。 你首先告诉它moveUp,但是立即用另一个moveUp覆盖那个动作,这次用一个完成块来运行moveDown。 然后,你立即用moveDown覆盖那个动作,所以基本上,你所做的只是告诉节点moveDown,一切都是多余的。

我知道它已被标记为答案,但我会提供一个替代scheme。

另一个select是简单地按照一个完成处理程序对动作进行sorting

例如(如果你愿意的话,可以写成单行):

 NSArray *actions = @[moveUp, [SKAction unhide], moveDown]; SKAction *action = [SKAction sequence:actions]; 

然后在你的循环中只写:

 [node runAction:action withCompletion^{ NSLog(@"STARTING MOVEMENT"); }]; 

希望有人会觉得这有用。