我可以在SceneKit对象上使用PNG序列作为动画素材吗?

我想以编程方式更改在iOS中使用SceneKit呈现的对象的材质。 但我想使用动画图像文件。 对于像UIImageViews这样的东西,PNG序列在iOS中运行良好 – 我如何将它们用作SceneKit中的素材?

这样的东西不起作用:

floor.firstMaterial.diffuse.contents = [UIImage animatedImageNamed:@"ANIMATION_" duration:6.0f]; 

谢谢!

没有任何东西你可以开箱即用。

我会使用着色器修饰符来完成此操作。 如果将所有图像打包在单个图像中,则可以使用修改器(在SCNShaderModifierEntryPointGeometry入口点)根据u_time更新对象的纹理坐标,以便每隔t ms使用另一个图像(或图集的子图像) 。

有一个更简单的解决方案(或者至少我认为它更简单)虽然我无法certificate它是否更有效。 我已经在iPad mini(第一代)上进行了测试,它运行正常。

您可以将SKScene对象放置在那里,而不是将作为spritesheet的纹理放置到材质的内容中(并使用着色器)。

这样,您就可以在SKScene中使用SKSpriteNode对象,并使用SCNAction对象为它们设置动画。 然后,无需触摸着色器代码即可轻松控制所有动画,并且function更强大。

  NSArray *cursorTextures = @[ [SKTexture textureWithImageNamed:@"tilecursor1.png"], [SKTexture textureWithImageNamed:@"tilecursor2.png"], [SKTexture textureWithImageNamed:@"tilecursor3.png"], [SKTexture textureWithImageNamed:@"tilecursor4.png"], [SKTexture textureWithImageNamed:@"tilecursor5.png"] ]; SKSpriteNode *cursorSprite = [SKSpriteNode spriteNodeWithTexture:cursorTextures[0]]; cursorSprite.position = CGPointMake(cursorSprite.size.width/2.0, cursorSprite.size.height/2.0); [cursorSprite runAction:[SKAction repeatActionForever:[SKAction animateWithTextures:cursorTextures timePerFrame:0.1]]]; SKScene *cursorScene = [SKScene sceneWithSize:cursorSprite.size]; cursorScene.backgroundColor = [UIColor clearColor]; [cursorScene addChild:cursorSprite]; ... self.cursor.material.diffuse.contents = cursorScene; 

Swift 4.1 / Xcode 9.3 / iOS 11.3

您可以使用CADisplayLink滚动自己的动画来解决此问题

将图像加载到UIImage数组中

 var images : [UIImage] = [ UIImage(named: "image1.png"), UIImage(named: "image2.png"), ... ] 

然后,开始动画:

 var animationImageFrameIndex : Double = 0 var displayLink : CADisplayLink? func startAnimation() { animationImageFrameIndex = 0 displayLink = CADisplayLink(target: self, selector: #selector(animationStep(_:))) displayLink!.preferredFramesPerSecond = 60 displayLink!.add(to: .current, forMode: .defaultRunLoopMode) } 

preferredFramesPerSecond是您希望调用animationStep方法的所需速率。 但是, CADisplayLink不保证会以您请求的速率调用它。

animationStep函数由CADisplayLink定期调用 ,实际上循环遍历图像:

 @objc func animationStep(_ displayLink: CADisplayLink) { let desiredFPS : Double = 24 let realFPS = 1 / (displayLink.targetTimestamp - displayLink.timestamp) material.diffuse.contents = images[Int(animationImageFrameIndex)] animationImageFrameIndex += desiredFPS / realFPS if Int(animationImageFrameIndex) >= images.count { displayLink.remove(from: .current, forMode: .defaultRunLoopMode) } } 

在上面的方法中, desiredFPS是您实际想要在动画中使用的帧速率。

这里有一个关于Bitbucket的完整示例项目。

应该能够使用简单的CAKeyframeAnimation为此(一系列图像)设置动画,但经过大量测试后,很明显它不起作用,这似乎是Apple方面的一个错误。 这里有一个开放的雷达来自其他人,我也提交了一份错误报告。