【问题标题】:Do I have to manually remove emitter node from parent after it's done playing?完成播放后,我是否必须手动从父节点中删除发射器节点?
【发布时间】:2015-02-03 19:35:40
【问题描述】:

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

我有这段代码:

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

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

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

由于我的项目被设计为让精灵经常相互碰撞,我想确定是否仍需要手动处理以防止内存泄漏(粒子层有很多已完成的子发射器节点已经玩了)

【问题讨论】:

  • 你必须自己删除它。
  • @hamobi 感谢您的评论。是否有在发射器节点播放完毕时触发的事件/方法,以便我可以检测何时删除它?
  • 不,我不这么认为。我只是在一段时间后使用 SKAction 将其删除

标签: ios swift sprite-kit skemitternode


【解决方案1】:

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

其实很简单。您可以创建一个 SKAction 序列,其中包含一个等待动作(1 秒或仅比效果长度稍长一点)和一个 removeFromParent 动作。

这将在它完成后立即消除它,并确保您的帧速率不会下降。

【讨论】:

    【解决方案2】:

    简短的回答是不,您无需担心。但是,如果粒子发射器不在屏幕上或永久运行,它就会成为一个更大的问题。当场景被释放时,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];
    

    【讨论】:

    • 感谢您的解释。这有帮助:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    • 1970-01-01
    相关资源
    最近更新 更多