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

我有以下代码片段:

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

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

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

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

最佳答案

简短的答案是“不”,您无需为自己的情况而担心。但是,如果粒子发射器不在屏幕上或永久运行,则成为更大的问题。释放场景后,将自动删除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];

10-06 00:03