可以为SKTexture设置图像动画吗? 建议的解决方案:粒子动作自iOS 9以来似乎不起作用解决方法:实现自己的发射器

问题描述

我创建了一个SKEmitterNode,并且我希望使用particleTexture属性为图像设置动画。

这是我正在尝试的方法,但仅显示一个图像:

let animationImages = [UIImage(named: "image1")!,UIImage(named: "image2")!]

  let imageView = UIImageView()
  imageView.image = UIImage.animatedImage(with: animationImages,duration: 1)
  imageView.startAnimating()

  emitter.particleTexture = SKTexture(image: imageView.image!)

解决方法

无论动画如何,最后一行将始终返回相同的“主”图像。此问题已在此站点的其他地方得到确认,但另请参见UIImageView.image中的Apple's documentation

但是,即使您确实设法获得了当前图像,它仍然是一次性的任务,并且纹理不会自动更新;那是你需要自己做的事情;正如苹果在其SpriteKit参考中的Animating a Sprite by Changing its Texture中所说的那样:

精灵的纹理属性指向其当前纹理。您可以更改此属性以指向新的纹理。

建议的解决方案:粒子动作(自iOS 9以来似乎不起作用)

幸运的是,有一个SKAction可以做到这一点(有关更多详细信息,请参见最后一个链接),并且理论上它甚至可以应用于SKEmitterNode粒子(我刚发现时正要告诉你相反的情况):

let animationTextures = [SKTexture(imageNamed: "image1"),SKTexture(imageNamed: "image2"),SKTexture(imageNamed: "image3")]
let animationAction = SKAction.repeatForever(SKAction.animate(with: textures,timePerFrame: 0.1))
emitter.particleAction = animationAction

编辑:它行不通,并且已经运行了多年:particleAction简直被忽略了。令人难以置信的是,苹果公司无法修复如此明显的错误长达五年,但这似乎是事实。

解决方法:实现自己的发射器

SKEmitterNode对他们有很多帮助(尽管有此错误):

  • 粒子是轻量的,精简的SKSpriteNode类事物,经过优化可大量抛出,而没有与成熟的sprite节点相关的所有开销。
  • 可以在XCode的可视化设计器中构建发射器,与以编程方式创建所有内容相比,可以节省大量时间。

但是,我曾经发现自己曾经被迫实施自己的“发射器”。就我而言,它只涉及编写一种方法来创建固定数量的Sprite节点,并将一个复杂的动作(多个组和序列的三个层次的层次结构)附加到每个方法上,以控制它们的移动,缩放,alpha和最终失踪(从父母那里移走)。这不是很多工作,它给了我所需的精确控制,以控制发射器节点无法提供的粒子动画–但是我很幸运,因为我一次只需要发射几十个粒子。

我想说,如果满足以下所有条件,则实现自己的发射器最有意义:

  • 您确实需要纹理动画并且迫不及待地希望Apple修复该错误,并且/或者您需要SKEmitterNode没有提供的其他某些粒子行为;
  • 您不需要大量的粒子,尤其是并发的粒子(因此性能仍然可以接受);
  • 您不介意在没有可视设计器的情况下以编程方式完成所有的发射器设计工作-尽管您仍可以将发射器作为Xcode中的SKEmitterNode进行原型设计,并在最终版本中重用原型的参数实施;
  • 您的粒子动画(即,位置,比例,alpha,旋转,色调,纹理(首先要这么做的原因)的所有变化)都不会让您感到不知所措:在我的情况下,我只需要实现一种特殊情况(我仍然可以解决其复杂性),但是如果我需要设计多个这样的发射器,我可能最终会创建一个类与{{1 }},这可能不是一件简单的任务。

再一次,祝您好运:SKEmitterNode可能是一个很棒的框架,如果只有Apple能够修复其一些非常令人毛骨悚然的错误。 (我在使用自定义着色器时遇到问题。也许您会在不久的将来看到我的一个或两个问题。)

,
  let image1 = SKAction.run( { emitter.particleTexture = SKTexture(imageNamed: "image1") } )
  let image2 = SKAction.run( { emitter.particleTexture = SKTexture(imageNamed: "image2") } )
  let image3 = SKAction.run( { emitter.particleTexture = SKTexture(imageNamed: "image3") } )
  
  let seq = SKAction.sequence([image1,wait,image2,image3,wait])
  let repeater = SKAction.repeatForever(seq)
  emitter.run(repeater)