Skip to main content
 首页 » 操作系统

animation之在 SceneKit 中动画化 UV

2024年01月01日30over140

我正在寻找一种在 SceneKit 中制作 Sprite 表动画的方法。经过一些研究,我找到了 Core Animation 方法来执行此操作,这将是完美的,因为我需要尽可能多地控制动画。

我准备了一个简单的平面网格,其 UV 限制为一个 spritesheet 帧的大小。这样我只需要水平地设置 UV 的动画。我发现 Material 的 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") 

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

请您参考如下方法:

这里有两个问题。

  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 中以传递给 fromValue 和 toValue,因为 Swift 不能不会像对标量数字类型那样自动转换它。

另请注意,您可以根据需要对 Float.infinity 使用类型推断。