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

23
我需要将粒子发射器效果在两个位置上重复显示(用于分屏目的),我想知道是否有人知道如何实现这一点。我的目标是在iOS 10上运行。以下是我迄今为止尝试过的方法:
  1. targetNode赋值给SKNode,然后每帧复制SKNode:在iOS 10上不起作用。
  2. 将粒子发射器分配给SKNode,并使用view.textureFromNode生成纹理以便每帧进行复制:太慢了,需要1/120帧的时间。
  3. 将自定义操作分配给粒子节点,将节点复制到另一个SKNode中:在iOS 10上不运行动作。
  4. 复制现有的粒子节点,希望种子不是随机的:种子是随机的。
  5. 尝试在更新时复制粒子发射器:粒子只会在原点产生。
  6. 尝试使用SKReferenceNode:仅是发射器的副本,单独运行。
我唯一能想到真正发射的选项是编写自己的粒子发射器,但我想避免这样做,所以我想知道是否有人遇到过这个问题,并知道实现所需效果的解决方案。
另外一件事是我可以预渲染发射器,但如果我采用这种方法,将会占用大量纹理内存。
编辑:为了帮助可视化,我画了一张图片,白色边框显示分屏位置,黑色边框显示场景包裹位置。enter image description here
截至目前,Player 1和Player 2都在原始场景中。

第二位玩家正在向右走,即将撞上世界边缘以将其移动到世界的左侧,但他尚未撞上。因此,我需要复制发生的场景,以视觉上看起来像一个场景。由于玩家1仍在原始场景中,原始发射器需要保持原样。玩家2将不得不看到副本中发生的相同图像,否则一旦他穿过边界,将会出现“故障”效果,包围的幻象就消失了。

最终结果:

我们只是说了“算了”,玩家1和玩家2将查看不同的发射器节点,我们只需在需要时将发射器附加到每个玩家的摄像机上。


@Whirlwind,我知道,如果可以的话我会付出超过500美元的奖金。现在我正在研究使用SKVideoNode。我正在测试使用它与将所有粒子节点帧保留在内存中时的性能差异。 - Knight0fDragon
我也提交了一个请求来种植随机数,为什么CAEmitterLayer允许种子但SKEmitterNode不允许,这超出了我的理解哈哈。 - Knight0fDragon
不过为什么不这样做呢?因为我不想让效果看起来一成不变哈哈,所以我需要编写一个机制来缓存和重建视频,每当有后台时间可用时,就会产生新的发射器的错觉。我会告诉你它的表现如何。 - Knight0fDragon
@Knight0fDragon,不是要抢了你的问题,但我也在开发一个双人游戏,没有考虑到使用2个SKViews选项...太棒了。至于限制Update调用一次,你是怎么做到的?只是在其中一个场景上设置一个变量并在更新时检查吗?还是有更优雅的方法?您能分享关于此方法的任何其他陷阱或“注意事项”吗?谢谢。 - Ron Myschuk
1
@RonMyschuk,“当前时间”在不同视图之间的更新中是一致的。 您需要捕获此值并将其存储在变量中。 下次调用更新时,请检查此值,如果存储的当前时间=更新当前时间,则将其标记为false并返回。 对于所有更新调用都执行此操作。 请注意,这将因为被调用两次而在许多方面影响SKPhysics。 我还没有找到一个优雅的方法来解决这个问题。 - Knight0fDragon
显示剩余7条评论
1个回答

7

我猜这个功能应该是按预期工作的,但是我不知道它的性能如何以及它是否符合你的需求和当前游戏。无论如何,也许它可以在某种程度上帮助你。首先,在你的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是在storyboard中使用自动布局定义的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];
}

我知道你可能不需要所有这些代码,但如果你某种程度上需要,我会为了完整性而发布它。以下是结果:enter image description here


感谢@Whirlwind,我已经使用了2个视图来创建分屏效果(在相机的帮助下更加疯狂)。但问题在于没有场景包装功能,因此需要复制节点来进行场景包装。这个问题出现在当玩家1向左移动而玩家2向右移动时。两者都触碰到了世界边缘,所以原始世界在一侧,复制的世界在另一侧。(每个视图的对面)在这种情况下,我将需要2个发射器。 - Knight0fDragon
如果这是单人游戏的话,我只需要交换SKEmitterNode来保持主要的发射器在场景上,但在分屏世界中,我不再拥有这个特权。 - Knight0fDragon
这个“渲染到纹理”显然需要一些形式的渲染,这意味着需要相机或其他粒子传输方式。我正在进行构思,但感觉有点困难。 - Confused
但是,请考虑一下,可能可以将SceneKit场景渲染到SpriteKit视图中。这可能是一种方法吗?我对SceneKit的粒子系统的经验大多是积极的。它不像虚幻粒子那样强大,但即使在旧硬件上也具有相当的性能。 - Confused
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Knight0fDragon
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接