播放完毕后,我是否必须从父级手动移除发射器节点?
Do I have to manually remove emitter node from parent after it's done playing?
我目前在我的 sprite 与游戏中的另一个 sprite 碰撞时显示粒子效果。
我有这段代码:
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];
我实际上建议您移除发射器。我最近在我的游戏中遇到一个问题,因为我没有移除发射器,它会开始非常严重地滞后。这是一个问题,当添加发射器时我能够 100% 重现,所以我知道它们是帧速率下降的唯一原因。在我开始看到延迟之前,大约需要 20 个未移除的发射器。
其实很简单。您可以创建一个 SKAction 序列,其中包含一个等待动作(1 秒或稍微超过您的效果长度)和一个 removeFromParent 动作。
这将在它完成后立即摆脱它,并确保您的帧率不会下降。
我目前在我的 sprite 与游戏中的另一个 sprite 碰撞时显示粒子效果。
我有这段代码:
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];
我实际上建议您移除发射器。我最近在我的游戏中遇到一个问题,因为我没有移除发射器,它会开始非常严重地滞后。这是一个问题,当添加发射器时我能够 100% 重现,所以我知道它们是帧速率下降的唯一原因。在我开始看到延迟之前,大约需要 20 个未移除的发射器。
其实很简单。您可以创建一个 SKAction 序列,其中包含一个等待动作(1 秒或稍微超过您的效果长度)和一个 removeFromParent 动作。
这将在它完成后立即摆脱它,并确保您的帧率不会下降。