Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 在SceneKit中添加和转换动画_Swift_Animation_Scenekit - Fatal编程技术网

Swift 在SceneKit中添加和转换动画

Swift 在SceneKit中添加和转换动画,swift,animation,scenekit,Swift,Animation,Scenekit,我查看了WWDC中的香蕉游戏,该游戏是用Objective-C编写的,它试图将代码转换为Swift以导入动画并在它们之间转换,但我在从DAE文件运行Swift中的动画时遇到了问题 我有3dsMax的AutoDesk格式和openCollada格式的导出器DAE文件。动画的Autodesk格式适用于每个骨骼,因此我无法按名称调用动画,因此我只需导入场景并执行以下操作,以便在加载文件后立即开始动画 scene = SCNScene(named: "monster.scnassets/monsterS

我查看了WWDC中的香蕉游戏,该游戏是用
Objective-C
编写的,它试图将代码转换为
Swift
以导入动画并在它们之间转换,但我在从DAE文件运行Swift中的动画时遇到了问题

我有3dsMax的AutoDesk格式和openCollada格式的导出器DAE文件。动画的Autodesk格式适用于每个骨骼,因此我无法按名称调用动画,因此我只需导入场景并执行以下操作,以便在加载文件后立即开始动画

scene = SCNScene(named: "monster.scnassets/monsterScene.DAE") 
scene2 = SCNScene(named:"monster.scnassets/monster.DAE")

var heroNode = SCNNode()
heroNode = scene.rootNode.childNodeWithName("heroNode", recursively: false)!

var nodeArray = scene2.rootNode.childNodes

for childNode in nodeArray {
    heroNode.addChildNode(childNode as SCNNode)
}
虽然动画一开始就播放,但我知道如何存储动画

如果我使用openCollada导出collada文件。我可以使用以下命令来运行获取并运行动画,因为对于AutoDesk collada格式,整个对象只有一个动画,而不是每个骨骼。通过这种方式,我还可以使用
CAAnimation
存储动画

var anim = scene2.rootNode.animationForKey("monster-1")
childNode.addAnimation(anim, forKey: "monster-1")  
但是角色会以一定角度跑,也会来回跑,而不是在同一个点上跑

此外,使用openCollada的照明效果更好。我只想使用openCollada而不是autodesk collada export。现在,我使用openCollada格式导出场景,使用autodesk导出角色


如何在
SceneKit
/
Swift
中存储动画,以及动画之间的转换?谢谢。

如果从文件加载场景时不更改默认选项,场景中的所有动画将立即自动附加到其目标节点并播放。(请参阅SceneKit API参考中的。)

如果要从场景文件加载动画并保留它们以便稍后附加到节点(即播放),最好将它们与类一起加载。此外,您可以(但不必)将基础模型存储在一个文件中,将动画存储在其他文件中


看看这个香蕉动画加载代码。看看吧

这里发生了什么:

  • 有一个自定义类管理动画角色。它拥有一个包含角色模型的
    SCNNode
    ,以及一堆
    CAAnimation
    s,用于模型可以做的所有事情(空闲/跳转/抛出等)
  • 该类通过传递从一个DAE文件加载的字符节点来初始化。(
    AAPLGameSimulation loadNodeWithName:FromSceneName:
    是一个方便的包装器,用于从文件中加载
    SCNScene
    ,并从中获取命名节点。)该DAE文件只包含角色模型,不包含动画
  • 然后,
    AAPLMonkeyCharacter
    从包含每个动画的单独DAE文件加载(并存储对)所需动画的引用。这就是
    SCNSceneSource
    的用武之地——它可以让你在不播放动画的情况下从文件中抓取动画
  • 播放时,monkey类调用
    addAnimation:forKey:
    在其主节点上运行动画

  • 翻译成Swift并应用到你的问题中——你的所有动画似乎都在同一个文件中——我会这样做(一个假设类的模糊轮廓):

    关键位:

    • scnscensourceanimationimportpolicydonotplay
      确保从场景源加载的节点不会以附加/播放动画开始
    • 您必须使用
      entryWithIdentifier:withClass:
      单独加载动画。在连接到节点之前,请确保按照您喜欢的方式配置它们(重复、淡入淡出持续时间等)

    谢谢,我会查出来的我甚至不能推翻你的答案。需要15个代表。
    // In AAPLGameLevel.m:
    SCNNode *monkeyNode = [AAPLGameSimulation loadNodeWithName:nil fromSceneNamed:@"art.scnassets/characters/monkey/monkey_skinned.dae"];
    AAPLMonkeyCharacter *monkey = [[AAPLMonkeyCharacter alloc] initWithNode:monkeyNode];
    [monkey createAnimations];
    
    // In AAPLSkinnedCharacter.m (parent class of AAPLMonkeyCharacter):
    + (CAAnimation *)loadAnimationNamed:(NSString *)animationName fromSceneNamed:(NSString *)sceneName
    {
        NSURL *url = [[NSBundle mainBundle] URLForResource:sceneName withExtension:@"dae"];
        SCNSceneSource *sceneSource = [SCNSceneSource sceneSourceWithURL:url options:nil ];
        CAAnimation *animation = [sceneSource entryWithIdentifier:animationName withClass:[CAAnimation class]];
        //...
    }
    
    // In AAPLMonkeyCharacter.m:
    - (void)update:(NSTimeInterval)deltaTime
    {
        // bunch of stuff to decide whether/when to play animation, then...
        [self.mainSkeleton addAnimation:[self cachedAnimationForKey:@"monkey_get_coconut-1"] forKey:nil];
        //...
    }
    
    class Monster {
        let node: SCNNode
        let attackAnimation: CAAnimation
    
        init() {
            let url = NSBundle.mainBundle().URLForResource(/* dae file */)
            let sceneSource = SCNSceneSource(URL: url, options: [
                SCNSceneSourceAnimationImportPolicyKey : SCNSceneSourceAnimationImportPolicyDoNotPlay
            ])
            node = sceneSource.entryWithIdentifier("monster", withClass: SCNNode.self)
            attackAnimation = sceneSource.entryWithIdentifier("monsterIdle", withClass: CAAnimation.self)
        }
    
        func playAttackAnimation() {
            node.addAnimation(attackAnimation, forKey: "attack")
        }
    }