序列可以分解为多个子序列,SKAction
这样,一旦特定子序列完成,它将不再运行,因此不会在解码时重新启动。
编码
制作一个轻量级、可编码的对象,它可以管理序列,将其分解为子序列并记住(在编码时)已经运行的内容。我在 GitHub 上的库中编写了一个实现。这是 gist 中代码的当前状态。
这是一个示例(使用与以下相同的顺序):
HLSequence *xyzSequence = [[HLSequence alloc] initWithNode:self actions:@[
[SKAction waitForDuration:10.0],
[SKAction performSelector:@selector(doY) onTarget:self],
[SKAction waitForDuration:1.0],
[SKAction performSelector:@selector(doZ) onTarget:self] ]];
[self runAction:xyzSequence.action];
这个概念
第一个想法:将序列拆分为几个独立的子序列。随着每个子序列完成,它将不再运行,因此如果应用程序被保留,则不会被编码。例如,像这样的原始序列:
[self runAction:[SKAction sequence:@[ [SKAction performSelector:@selector(doX) onTarget:self],
[SKAction waitForDuration:10.0],
[SKAction performSelector:@selector(doY) onTarget:self],
[SKAction waitForDuration:1.0],
[SKAction performSelector:@selector(doZ) onTarget:self] ]]];
可以这样拆分:
[self runAction:[SKAction sequence:@[ [SKAction performSelector:@selector(doX) onTarget:self] ]]];
[self runAction:[SKAction sequence:@[ [SKAction waitForDuration:10.0],
[SKAction performSelector:@selector(doY) onTarget:self] ]]];
[self runAction:[SKAction sequence:@[ [SKAction waitForDuration:11.0],
[SKAction performSelector:@selector(doZ) onTarget:self] ]]];
无论何时对节点进行编码,方法doX
、doY
和doZ
都只会运行一次。
但是,根据动画的不同,等待的持续时间可能看起来很奇怪。例如,假设应用程序在 1 秒延迟之前被保留doX
并已运行。然后,在恢复时,应用程序将不会运行或再次运行,但会等待 11 秒后再运行。doY
doZ
doX
doY
doZ
为了避免可能出现的奇怪延迟,请将序列拆分为一系列相关子序列,每个子序列都会触发下一个子序列。例如,拆分可能如下所示:
- (void)doX
{
// do X...
[self runAction:[SKAction sequence:@[ [SKAction waitForDuration:10.0],
[SKAction performSelector:@selector(doY) onTarget:self] ]]];
}
- (void)doY
{
// do Y...
[self runAction:[SKAction sequence:@[ [SKAction waitForDuration:1.0],
[SKAction performSelector:@selector(doZ) onTarget:self] ]]];
}
- (void)doZ
{
// do Z...
}
- (void)runAnimationSequence
{
[self runAction:[SKAction performSelector:@selector(doX) onTarget:self]];
}
有了这个实现,如果序列在之后被保留doX
并且doY
已经运行,那么在恢复时,之前的延迟doZ
将只有 1 秒。当然,它是一整秒(即使在编码之前已经过去了一半),但结果是相当可以理解的:编码时序列中正在进行的任何操作都将重新启动,但一旦完成,它就完成了。
当然,制作一堆这样的方法是很讨厌的。相反,创建一个序列管理器对象,当触发它时,它会将序列分解为子序列,并以有状态的方式运行它们。