在SceneKit中设置UV动画

时间:2014-12-05 20:14:44

标签: animation swift core-animation scenekit

我正在寻找一种在SceneKit中为精灵表制作动画的方法。经过一些研究后,我找到了Core Animation这样做的方法,这将是完美的,因为我需要尽可能多地控制动画。

我准备了一个简单的平面网格,其UV限制为一个spritesheet框架的大小。这样我只需要水平设置UV动画。我发现材料的contentsTransform矩阵的相关元素是m14(负责水平翻译的那个)。

但是,在运行时,SceneKit会回显以下错误:

[SCNKit ERROR] geometry?.firstMaterial?.diffuse.contentsTransform.m14 is not an animatable path

这是相关代码:

let spritesheetAnimation = CABasicAnimation(keyPath: "geometry?.firstMaterial?.diffuse.contentsTransform.m14")
spritesheetAnimation.fromValue = 1 - 1 / spritesheetFrameCount
spritesheetAnimation.toValue = 0
spritesheetAnimation.byValue = 1 / spritesheetFrameCount
spritesheetAnimation.duration = 1.0
spritesheetAnimation.repeatCount = Float.infinity

node.geometry?.insertMaterial(material, atIndex: 0)
node.addAnimation(spritesheetAnimation, forKey: "SpritesheetAnimation")

任何有此经验的人?我不知道是否有更简单的方法可以做到这一点,或者我是以错误的方式或任何方式看待它。所以,任何指针都会受到赞赏!

3 个答案:

答案 0 :(得分:3)

这里有两个问题。

  1. CoreAnimation将可动画的关键路径扩展到它可以设置动画的数据结构中 - 也就是说,它不是仅仅在一个完整的CATransform3D和另一个完整的transform.translation.x之间设置动画,而是让您为描述某个成员或属性的关键路径设置动画变换(如contentsTransform)。

    SceneKit不会这样做 - 您只能为完整的结构值设置动画。也就是说,您只能为contentsTransform.something制作动画,而不能为SCNMatrix4设置动画,为此,您需要提供完整的toValue作为fromValue / geometry?.firstMaterial?.diffuse.contentsTransform的动画。动画。

  2. KVC密钥路径与Swift选项无关,因此let spritesheetAnimation = CABasicAnimation(keyPath: "geometry.firstMaterial.diffuse.contentsTransform") let translation = SCNMatrix4MakeTranslation(1 - 1 / spritesheetFrameCount, 0, 0) spritesheetAnimation.fromValue = NSValue(SCNMatrix4: translation) spritesheetAnimation.toValue = NSValue(SCNMatrix4: SCNMatrix4Identity) spritesheetAnimation.duration = 1.0 spritesheetAnimation.repeatCount = .infinity 不是合法的密钥路径。丢失问号,你应该没问题。

  3. 所以,你的代码应该看起来像这样(未经测试):

    SCNMatrix4

    请注意,您需要在NSValue中包含fromValue以传递给toValueFloat.infinity,因为Swift无法像标量数字一样自动转换它类型。

    另请注意,如果您愿意,可以使用{{1}}的类型推断。

答案 1 :(得分:0)

您可以尝试contentsTransform.translation.x - Core Animation在处理图层时非常聪明,因此SceneKit也可以处理它。

答案 2 :(得分:0)

这应该有效:

  • 删除“?”来自keypath
  • 水平翻译,目标是m41(不是m14)

让spritesheetAnimation = CABasicAnimation(keyPath:“geometry.firstMaterial.diffuse.contentsTransform.m41”)

[...]

SceneKit不会将矩阵分解为“转换/旋转/缩放”等组件,因此您无法使用“contentsTransform.translation.x”之类的路径。但您仍然可以在显式动画键路径中定位矩阵组件,如“contentsTransform.m41”。