2

我正在尝试让 SKNode 根据命令移动到屏幕上。我已经设置了以下 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");
        }];

但是,SKAction 似乎没有以正确的顺序触发。我使用了代码,这样一旦完成了一个步骤,下一步就会开始。但是,在下一个 SKAction 开始工作之前,SKAction 似乎没有足够快地移动节点。我的印象是,使用完成调用意味着下一个动作要等到前一个动作完成后才会开始?这似乎不是这里的情况。此外,如果我为第 1 步(向上移动)留出足够长的持续时间,它将跳过第 2 步(向下移动)并开始执行第 3 步(开始移动)。我完全不知道这怎么可能。如果有人能指出我在理解如何正确地将不同的动作链接在一起的错误,我将不胜感激。

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

4

3 回答 3

10

您似乎不了解 runAction 是如何执行的。

使用

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

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

其次,在一个函数/块中进行的两个 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");
        }];
    }];
于 2014-01-08T05:10:58.263 回答
1

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

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

您现在所拥有的将不起作用,因为您连续调用了三个 runAction。您首先告诉它 moveUp,然后立即用另一个 moveUp 覆盖该操作,这次使用运行 moveDown 的完成块。然后,您立即使用 moveDown 覆盖该操作,因此本质上,您所做的只是告诉节点 moveDown,其他一切都是多余的。

于 2014-01-08T05:11:00.507 回答
1

我知道它已被标记为已回答,但我会提供替代方案。

另一种选择是仅使用一个完成处理程序对操作进行排序

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

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

然后在你的循环中写:

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

希望有人会发现这很有用。

于 2015-01-19T18:38:46.910 回答