【问题标题】:Animating UVs in SceneKit在 SceneKit 中为 UV 设置动画
【发布时间】:2015-02-04 02:24:00
【问题描述】:

我正在寻找一种在 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")

有人有这方面的经验吗?我不知道是否有更简单的方法可以做到这一点,或者我是否以错误的方式看待它或其他任何事情。因此,任何指针将不胜感激!

【问题讨论】:

    标签: animation swift core-animation scenekit


    【解决方案1】:

    这里有两个问题。

    1. CoreAnimation 将可动画化的关键路径扩展到它可以动画化的数据结构中——也就是说,它不仅可以在一个完整的 CATransform3D 和另一个之间设置动画,它还允许您对描述变换的某些成员或属性的关键路径进行动画处理(例如transform.translation.x)。

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

    2. KVC 键路径与 Swift 选项没有任何关系,因此geometry?.firstMaterial?.diffuse.contentsTransform 不是合法的键路径。丢掉问号,你应该没事。

    因此,您的代码应该如下所示(未经测试):

    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
    

    请注意,您需要将SCNMatrix4 包装在NSValue 中以传递给fromValuetoValue,因为Swift 无法像对标量数字类型那样自动转换它。

    还请注意,如果您愿意,您可以对 Float.infinity 使用类型推断。

    【讨论】:

    • 1.我有点期待这样的事情。不幸的是,这仍然显示相同的错误,当然只是将 geometry.firstMaterial.diffuse.contentsTransform 称为不是可动画路径,SceneKit 文档指出它是.. 2. 也考虑到了这一点。但是,更改它并没有解决它,所以我认为我会安全行事。感谢您的解释!
    【解决方案2】:

    你可以试试contentsTransform.translation.x——Core Animation 在处理图层时非常聪明地处理变换,所以 SceneKit 或许也能处理。

    【讨论】:

    • 看起来很有希望,不幸的是同样的错误:/
    • 谢谢。我要再等一会儿;可能仍然是我的错误。
    【解决方案3】:

    这应该可行:

    • 删除“?”从密钥路径
    • 水平平移,目标 m41(不是 m14)

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

    [...]

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

    【讨论】:

    • 显示同样的错误,恐怕。真的没想到运行时会抱怨一个矩阵组件而不是另一个.. 无论如何谢谢:)
    猜你喜欢
    • 1970-01-01
    • 2014-10-07
    • 1970-01-01
    • 2016-02-27
    • 2021-12-21
    • 2020-12-13
    • 1970-01-01
    • 2018-06-07
    • 2012-09-23
    相关资源
    最近更新 更多