【问题标题】:SceneKit load node with animation from separate scn fileSceneKit 从单独的 scn 文件加载带有动画的节点
【发布时间】:2017-04-29 01:32:55
【问题描述】:

我有一个动态创建 SCNView 的视图。它的场景是空的,但是当我按下按钮时,我想从单独的 scn 文件中添加一个节点。该文件包含动画,我希望它在主场景中制作动画。问题是在将对象添加到场景后它没有动画。当我将此文件用作 SCNView 场景时,它可以工作。 isPlaying 和循环已启用。我还需要做什么才能导入带有动画的此类节点?示例代码如下:

override func viewDidLoad() {
    super.viewDidLoad()

    let scene = SCNScene()
    let sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
    sceneView.scene = scene
    sceneView.loops = true
    sceneView.isPlaying = true
    sceneView.autoenablesDefaultLighting = true
    view.addSubview(sceneView)


    let subNodeScene = SCNScene(named: "Serah_Animated.scn")!
    let serah = subNodeScene.rootNode.childNode(withName: "main", recursively: false)!

    scene.rootNode.addChildNode(serah)


}

【问题讨论】:

  • 和你一样的问题,你解决了吗?

标签: ios animation 3d scenekit


【解决方案1】:

您需要从场景Serah_Animated.scn 中获取动画,这将是一个CAAnimation 对象。然后将该动画对象添加到主场景的 rootNode。

let animScene = SCNSceneSource(url:<<URL to your scene file", options:<<Scene Loading Options>>)
let animation:CAAnimation = animScene.entryWithIdentifier(<<animID>>, withClass:CAAnimation.self)

您可以使用Xcode中的场景编辑器从.scn文件中找到animID,如下所示。

现在您可以将动画对象添加到您的根节点。

scene.rootNode.addAnimation(animation, forKey:<<animID>>)

请注意,我们正在重用 animID,这也将允许您从节点中删除动画。

scene.rootNode.removeAnimation(forKey:<<animId>>)
  • 我上面的解决方案假设您的动画是单个动画。如果看到一堆动画,则需要添加所有动画节点。在我的工作流程中,我将 Blender 中的文件导出为 Collada 格式,然后使用 Automated Collada Converter 确保我有单个动画节点。
  • Related SO answer
  • 您也可以使用entriesWithIdentifiersOfClass(CAAnimation.self) 以编程方式获取animID,这在您有一堆动画而不是上面的单个动画时很有用,或者如果您只想添加动画而不用担心之前的animID .
  • Apple Sample Code for scene kit animations,请注意示例代码在 ObjC 中,但转换为 Swift 应该是直截了当的。

【讨论】:

  • 我没有在 .scn 文件中找到实体列表。它只存在于 .dae 文件中
【解决方案2】:

您只需要检索动画:

        [childNode enumerateChildNodesUsingBlock:^(SCNNode *child, BOOL *stop) {
        for(NSString *key in child.animationKeys) {               // for every animation key
            CAAnimation *animation = [child animationForKey:key]; // get the animation
            animation.usesSceneTimeBase = NO;                     // make it system time based
            animation.repeatCount = FLT_MAX;                      // make it repeat forever
            [child addAnimation:animation forKey:key];            // animations are copied upon addition, so we have to replace the previous animation
        }
    }];

【讨论】:

  • 谢谢@ooOlly。
  • [child animationForKey:] 自 iOS 11.0 起已弃用
猜你喜欢
  • 2018-05-15
  • 2017-01-17
  • 2015-07-15
  • 1970-01-01
  • 1970-01-01
  • 2018-02-08
  • 2016-07-04
  • 2012-12-27
  • 2017-03-17
相关资源
最近更新 更多