3

我目前在我的精灵与游戏中的另一个精灵碰撞时显示粒子效果。

我有这段代码:

let sparkParticle = SKEmitterNode(fileNamed: "SparkParticle.sks")
if sparkParticle.parent == nil
{
    sparkParticle.position = mySprite.position
    self._particleLayer.addChild(sparkParticle)
}
sparkParticle.resetSimulation()

我创建的粒子的出生率为 1000 个,最多为 100 个。我将粒子发射器节点的位置设置为我的精灵当前在屏幕上的位置。然后,我将它添加为粒子层节点的子节点。

我的问题是,粒子发射器节点完成后是否必须手动从其父节点中移除?还是 Sprite Kit 播放完毕后会自动删除?

由于我的项目旨在让精灵相互碰撞很多,我想确保我是否仍然需要手动处理以防止内存泄漏(粒子层有很多已经完成播放的子发射器节点)

4

2 回答 2

1

我实际上建议您移除发射器。我最近在我的游戏中遇到了一个问题,因为我没有移除发射器,所以它会开始严重滞后。添加发射器时我能够 100% 重现这是一个问题,所以我知道它们是帧速率下降的唯一原因。在我开始看到延迟之前,大约需要 20 个未移除的发射器。

这实际上很容易。您可以创建一个 SKAction 序列,其中包含一个等待动作(1 秒或仅超过您的效果长度)和一个 removeFromParent 动作。

这将在它完成后摆脱它,并确保你的帧速率不会下降。

于 2017-08-24T15:46:55.210 回答
0

简短的回答是不,你不需要担心你的情况。但是,如果粒子发射器不在屏幕上或永久运行,它就会成为一个更大的问题。当场景被释放时,SKEmitterNode 将被自动删除。因为 SKEMitterNode 是插入到节点树中的 SKNode。

但是,如果您想格外小心,您可以使用以下方法在场景释放之前手动递归地停止所有动作和发射器。在场景被解除分配并导致我的应用程序崩溃后,我遇到了延迟 SKActions 触发的问题,因此我在场景被解除分配之前手动停止了它们。

保留对旧场景的引用并在场景中调用它:

+(void)recursivelyStopAndRemoveNode:(SKNode*)node {

    // recursively call all children
    for (SKNode *childNode in [node children]) {
        [PCUtils recursivelyStopAndRemoveNode:childNode];
    }

    // stop emitters
    if ( [node isKindOfClass:[SKEmitterNode class]]) {
        SKEmitterNode* sken = (SKEmitterNode*)node;
        sken.targetNode = nil;
        sken.particleBirthRate = 0;
        NSLog(@"stopping emitter %@", node.name);
    }

    // stop any running actions
    [node removeAllActions];

    // remove me from my parent.
    [node removeFromParent];

}

然后,在您的 GameViewController 或您要更改场景的任何地方使用它:

SKScene *oldScene = skView.scene;
[skView presentScene:newScene transition:nil];
if (oldScene) 
   [PCUtils recursivelyStopAndRemoveNode:oldScene];
于 2015-02-03T22:43:59.487 回答