在 Sprite Kit 中复制粒子发射器效果

Posted

技术标签:

【中文标题】在 Sprite Kit 中复制粒子发射器效果【英文标题】:Duplicating a particle emitter effect in Sprite Kit 【发布时间】:2017-03-18 09:14:10 【问题描述】:

我需要一个粒子发射器效果在 2 个点上重复出现(出于分屏目的),我想知道是否有人遇到过这样做的方法。我的目标是让它在 ios 10 上运行。这是我到目前为止所尝试的。

    targetNode 分配给SKNode,然后每帧复制SKNodetargetNode 在我的iOS 10 中不起作用。 将粒子发射器分配给SKNode,并使用view.textureFromNode 制作纹理以复制每一帧:需要1/120 帧,对我来说太慢了。 将自定义操作分配给将节点复制到另一个的粒子节点SKNode:操作将不会在 iOS 10 上运行 复制现有粒子节点以希望种子不是随机的:种子是随机的 尝试在更新时复制粒子发射器:粒子仅在原点生成 试过 SKReferenceNode :只是发射器的一个副本,可以自己运行

真正发射我剩下的唯一选择是编写我自己的粒子发射器,我试图避免这种情况,所以我想知道是否有其他人遇到这个问题并且知道实现预期效果的解决方案。

我可以做的另一件事是预渲染发射器,但如果我走这条路,这将占用大量纹理内存。

编辑:为了帮助可视化,我画了一张图片,白色边框显示了分屏发生的位置。黑色边框显示场景环绕发生的位置。

截至目前,玩家 1 和玩家 2 都在原始场景中。

玩家 2 向右走,即将击中世界环绕以将他移动到世界的左侧,但他还没有击中它。所以我需要有一个正在发生的场景的副本,以便它在视觉上看起来像一个场景。由于玩家 1 仍在原始场景中,因此原始发射器需要保持原位。玩家 2 将不得不在副本中看到相同的图像,否则一旦他通过该边界,就会发生“故障”效果,并且包裹的错觉现在消失了。

最终结果:

我们刚刚说了 F%%% 它,玩家 1 和玩家 2 将查看不同的发射器节点,我们将在需要时将发射器附加到每个玩家的相机。

【问题讨论】:

距离赏金结束还有两天,仍然没有新的答案。我必须说这是出乎意料的。无论如何,如果我由于自动奖励规则而赢得了一半的赏金,我将再次提高赏金(250 分,因为这是我理论上可以获得的)。不过,像@EpicByte 或 0x141e 之类的一些人(我非常尊重并且多次向他们学习)对此发表评论仍然会很好。 @Whirlwind,我知道,如果可以的话,我会提供超过 500 个赏金。现在我正在考虑使用SKVideoNode。我正在测试使用它与将所有粒子节点帧保存在内存中的性能。 我也提交了随机播种的请求,为什么 CAEmitterLayer 允许播种,但 SKEmitterNode 不允许播种,这超出了我的范围,哈哈 视频节点是一个聪明的主意。它实际上是在动画昂贵时使用的。但不知道是正常工作还是有问题。我见过很少有人抱怨 SKVideoNode 的一些问题。但如果它有效,那为什么不呢。 @RonMyschuk 传入的“当前时间”在不同视图之间的更新中是一致的。您需要捕获此值并将其存储在变量中。下次调用更新检查此值,如果存储当前时间 = 更新当前时间,则将其标记为 false 并返回。对所有更新调用执行此操作。请注意,这会在很多方面与 SKPhysics 混淆,因为它被调用了两次,我还没有找到一种优雅的方式来解决这个问题 【参考方案1】:

这只是工作(我猜是预期的),但我不知道有多少性能或它如何满足您的需求和您当前的游戏。无论如何,也许它可以以某种方式帮助你。首先,在你的 GameViewController...分屏:)

#import "GameViewController.h"
#import "GameScene.h"

@implementation GameViewController

- (void)viewDidLoad

    [super viewDidLoad];

    // Configure the view.
    SKView * leftSKView = (SKView *)self.leftScene;
    leftSKView.ignoresSiblingOrder = YES;
    leftSKView.showsFPS = YES;
    leftSKView.showsNodeCount = YES;

    SKView * rightSKView = (SKView *)self.rightScene;
    rightSKView.ignoresSiblingOrder = YES;
    rightSKView.showsFPS = YES;
    rightSKView.showsNodeCount = YES;




    // Create and configure the scene.
    GameScene *scene = [GameScene nodeWithFileNamed:@"GameScene"];
    scene.scaleMode = SKSceneScaleModeAspectFill;

    // Present the scene.
    [leftSKView presentScene:scene];
    [rightSKView presentScene:scene];


leftScenerightScene 是在情节提要中定义的 UIView,使用自动布局分别占据半个屏幕。还有一个类更改为 SKView(它是 UIView)。相当琐碎...

然后在您的游戏场景中添加将在这两个视图之间共享的发射器。因为只使用了一个发射器,所以发射的粒子(它们如何移动)将被镜像。所以在游戏场景中,只需添加一个粒子:

-(void)didMoveToView:(SKView *)view 
    /* Setup your scene here */


    SKEmitterNode *emitter =  [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSBundle mainBundle] pathForResource:@"MyParticle" ofType:@"sks"]];
    emitter.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidX(self.frame));
    emitter.name = @"explosion";
    emitter.targetNode = self;
    [self addChild:emitter];

我知道你不需要所有这些代码,但如果这是你想要的,我会发布它以确保完整性。结果如下:

【讨论】:

@Knight0fDragon 希望你不介意 Obj-C 的回答,我不小心选择了 Obj-C 作为一种语言,所以我懒得做一个基于 Swift 的项目,哈哈。另外,如果这不是您想要的,请告诉我,我将删除它。但是,当我在设备上运行它时,发射器看起来是镜像的、克隆的......(无论正确的术语是什么 :))并且一切都以 60fps 运行。 感谢@Whirlwind,我已经在使用 2 个视图来创建分屏效果(使用相机变得更加疯狂),问题是没有场景环绕功能,所以你需要复制节点来场景包装。这个问题归结为玩家 1 向左走,而玩家 2 向右走。都撞到了世界的边缘,所以原世界在一边,副本世界在另一边。 (在每个视图的相对侧)在这种情况下我需要 2 个发射器 我了解 obj c 和 swift,所以我们在这方面做得很好,哈哈 如果这是单人游戏,我会交换 SKEmitterNode 以保持主发射器在场景中,但在分屏世界中,我不再拥有这种奢侈 @Knight0fDragon 好的,我(想)我明白了。我现在正在回家的路上,所以不能真正测试任何东西,但如果我以后想出一些东西,会告诉你的。无论如何,有趣的问题要解决。如果有一些内置功能会很好(我个人到目前为止还没有听说过类似的东西)。

以上是关于在 Sprite Kit 中复制粒子发射器效果的主要内容,如果未能解决你的问题,请参考以下文章

Sprite Kit iOS 中的慢动作

iOS 7 Sprite Kit 释放内存

Sprite Kit 中的 SKSpinLockSync 是啥以及如何修复它

(译)LearnOpenGL实际案例Breakout:粒子

iOS 如何在 Sprite Kit 游戏中创建音频淡入/淡出效果?

重复触发 AVAudioPlayer 时,大量 fps 下降(Sprite Kit)