加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swift – 在SceneKit中添加和转换动画

发布时间:2020-12-14 05:31:15 所属栏目:百科 来源:网络整理
导读:我看了WWDC中的Banana游戏,它是用Objective-C编写的,试图将代码转换为 swift以导入动画并在它们之间进行转换但是我在从DAE文件中以swift运行动画时遇到问题. 我有来自3DSMAx和openCollada格式的AutoDesk格式的导出器DAE文件. autodeskformat theimtation是针
我看了WWDC中的Banana游戏,它是用Objective-C编写的,试图将代码转换为 swift以导入动画并在它们之间进行转换但是我在从DAE文件中以swift运行动画时遇到问题.

我有来自3DSMAx和openCollada格式的AutoDesk格式的导出器DAE文件. autodeskformat theimtation是针对每个骨骼所以我无法按名称调用动画,所以我只是导入场景并执行以下操作,以便在文件加载后立即启动动画.

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文件.我可以使用以下命令来运行get并运行动画,因为在AutoDesk collada格式的情况下,整个对象只有一个动画而不是每个骨骼.通过这种方式,我也可以使用CAAnimation存储动画.

var anim = scene2.rootNode.animationForKey("monster-1")
        childNode.addAnimation(anim,forKey: "monster-1")

但是然后角色以某个角度运行并且来回运行而不是在同一个地方跑.

使用openCollada也可以更好地照明.我只想使用openCollada而不是autodesk collada export.现在我使用openCollada格式导出场景,使用autodesk导出角色.

如何在SceneKit中快速存储动画并在它们之间进行转换?谢谢. :d

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

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

只需看看这个Bananas动画加载代码.看看吧.00002

// 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];
    //...
}

这里发生了什么:

>有一个管理动画角色的自定义类.它拥有一个包含角色模型的SCNNode,以及模型可以执行的所有事情(idle / jump / throw / etc)的一堆CAAnimations.
>通过传递从一个DAE文件加载的字符节点来初始化该类. (AAPLGameSimulation loadNodeWithName:fromSceneNamed:是一个方便的包装器,用于从文件加载SCNScene并从中获取命名节点.)该DAE文件仅包含字符模型,没有动画.
>然后,AAPLMonkeyCharacter从包含每个动画的单独DAE文件加载(并存储对其所需动画的引用).这就是SCNSceneSource的用武之地 – 它可以让你从文件中获取动画而无需播放它们.
>当播放时,猴子类调用addAnimation:forKey:在其主节点上运行动画.

转换到Swift并应用于你的问题 – 你似乎在同一个文件中有所有动画 – 我会做这样的事情(一个假设类的模糊轮廓):

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")
    }
}

关键位:

> SCNSceneSourceAnimationImportPolicyDoNotPlay确保从场景源加载的节点不会以附加/播放的动画开始.>您必须使用entryWithIdentifier:withClass:分别加载动画.确保在连接到节点之前配置它们的方式(重复,淡入淡出持续时间等).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读