完成播放后,我是不是必须手动从父节点中删除发射器节点?

Posted

技术标签:

【中文标题】完成播放后,我是不是必须手动从父节点中删除发射器节点?【英文标题】: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 将其删除 【参考方案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];

【讨论】:

感谢您的解释。这有帮助:)

以上是关于完成播放后,我是不是必须手动从父节点中删除发射器节点?的主要内容,如果未能解决你的问题,请参考以下文章

如何从父 yaml 节点获取完整的 yaml 节点子对象?

如何为特定的 yaml-cpp 节点设置发射样式

RxJava 手动发出项目

我必须手动解构所有对象吗

在反应中从父dom节点中删除子组件

如何在Swift中正确地从父节点中删除SKSpriteNode的子类(要从数组中移除,屏幕上的空格......)?