2017-09-08 14 views
3

長いアニメーションの.daeモデルがあります。アニメーションには、ウォーキング、ランニング、打撃、死などのセグメントが含まれます。各セグメントの開始点と終了点のフレーム番号がわかります。私はまた、毎秒のフレームレートを知っています。だから、各セグメントの開始と終了の時間を得るのはかなり簡単です。SCNAnimationPlayerを特定の開始時刻と終了時刻に "トリミングする方法、iOS 11

私は完全なアニメーションをSCNAnimationPlayerオブジェクトとして取得できます。私が実験してきたのは、完全なアニメーションのコピーを作成してから、アニメーションのtimeOffsetと期間を設定することです。

let walkPlayer = fullPlayer.copy() as! SCNAnimationPlayer 
walkPlayer.stop() 
walkPlayer.animation.timeOffset = walk.offset 
walkPlayer.animation.duration = walk.duration 

次に、walkPlayerをBip01ノードに戻します(完全なアニメーションを取得した場所)。

私は(forKey:「散歩」)animationPlayerを呼び出すことにより、容易に十分な散歩を再生することができます(遊ぶ?。)

私は簡単に十分なアニメーションの再生時間と他の側面を変更することができます。しかし、アニメーションは常にフレーム0から始まります。私が.timeOffsetに入れた値は、無視されます。

SCNAnimationPlayerで見つかったSCNAnimationの開始フレームから終了フレームまで再生するにはどうすればよいですか?

+0

animationPlayer(forKey :)は、タイプCAKeyframeAnimationのアニメーションを含むCAAnimationGroupを返します。配列の値とkeyTimesを置き換えてアニメーションをトリミングし、keyTimesをシフトしてすぐに開始させることができます。残念ながら、animationPlayer(forKey :)はiOS11では廃止され、結果を操作することで新たに "未定義の動作が発生する"という結果になります。これはkeyPathを消去します。あなたの操作の前にキャッシングして置き換えることで、そのバグを回避してください。私はまだSCNAnimationPlayerがanimationPlayer(forKey :)に基づく変更をどのように置き換えることができないのか誰かが知りたがっています。 – pommy

+0

はい。私はいつかXcode 8のコードを使って遊んだり、CAAnimationGroupsはうまく動作しています...私はXcode 9のアイデアを持っています...少し実験します:) – AutomatonTec

答えて

2

キービットは、私はこれらが、私はCAAnimationGroupを使うと、「作物」のフルアニメーションを使用することができた後は

CAAnimation(scnAnimation: animation) 

SCNAnimation(caAnimation: animation) 

を見つけることでした。

ここに私が取り組んでいた私のTroll.swiftがあります。もちろん、やりたいことはたくさんありますが、少なくとも私は貧しい獣を散歩させて死ぬことができます。

class Troll: SCNNode { 
    var body:SCNNode! 

    static func timeRange(forStartingAtFrame start:Int, endingAtFrame end:Int, fps:Double = 30) -> (offset:TimeInterval, duration:TimeInterval) { 
     let startTime = self.time(atFrame: start, fps: fps) //TimeInterval(start)/fps 
     let endTime  = self.time(atFrame: end, fps: fps) //TimeInterval(end)/fps 
     return (offset:startTime, duration:endTime - startTime) 
    } 

    static func time(atFrame frame:Int, fps:Double = 30) -> TimeInterval { 
     return TimeInterval(frame)/fps 
    } 

    static func animation(from full:CAAnimation, startingAtFrame start:Int, endingAtFrame end:Int, fps:Double = 30) -> CAAnimation { 
     let range = self.timeRange(forStartingAtFrame: start, endingAtFrame: end, fps: fps) 
     let animation = CAAnimationGroup() 
     let sub = full.copy() as! CAAnimation 
     sub.timeOffset = range.offset 
     animation.animations = [sub] 
     animation.duration = range.duration 
     return animation 
    } 


    func load() { 

     guard let trollScene = SCNScene(named: "Models.scnassets/troll/troll.dae") else { 
      fatalError("Can't load the scene") 
     } 

     guard let troll_body = trollScene.rootNode.childNode(withName: "troll", recursively: true) else { 
      fatalError("found no troll") 
     } 

     guard let troll_weapon = trollScene.rootNode.childNode(withName: "troll_weapon", recursively: true) else { 
      fatalError("found no troll_weapon") 
     } 

     guard let troll_bracelet = trollScene.rootNode.childNode(withName: "troll_bracelet", recursively: true) else { 
      fatalError("found no troll_bracelet") 
     } 

     guard let bips = trollScene.rootNode.childNode(withName: "Bip01", recursively: true) else { 
      fatalError("found no Bip01") 
     } 

     guard let fullKey = bips.animationKeys.first else { 
      fatalError("Bip01 got no animation") 
     } 

     guard let fullPlayer = bips.animationPlayer(forKey: fullKey) else { 
      fatalError("Bip01 got no player for \(fullKey)") 
     } 
     let fullAnimation = CAAnimation(scnAnimation: fullPlayer.animation) 

     self.addChildNode(troll_body) 
     self.addChildNode(troll_weapon) 
     self.addChildNode(troll_bracelet) 
     self.addChildNode(bips) 

     self.body = bips 
     self.body.removeAllAnimations() 

     let walkAnimation = Troll.animation(from: fullAnimation, startingAtFrame: 10, endingAtFrame: 60) 
     walkAnimation.repeatCount = .greatestFiniteMagnitude 
     walkAnimation.fadeInDuration = 0.3 
     walkAnimation.fadeOutDuration = 0.3 
     let walkPlayer = SCNAnimationPlayer(animation: SCNAnimation(caAnimation: walkAnimation)) 
     self.body.addAnimationPlayer(walkPlayer, forKey: "walk") 

     let deathAnimation = Troll.animation(from: fullAnimation, startingAtFrame: 1810, endingAtFrame: 1850) 
     deathAnimation.isRemovedOnCompletion = false 
     deathAnimation.fadeInDuration = 0.3 
     deathAnimation.fadeOutDuration = 0.3 
     let deathPlayer = SCNAnimationPlayer(animation: SCNAnimation(caAnimation: deathAnimation)) 
     self.body.addAnimationPlayer(deathPlayer, forKey: "death") 

     self.scale  = SCNVector3(0.1,0.1,0.1) 

    } 

    func walk() { 
     print("+++ walk +++") 
     self.body.animationPlayer(forKey: "walk")?.play() 
    } 

    func death() { 
     print("+++ death +++") 
     self.body.animationPlayer(forKey: "walk")?.stop(withBlendOutDuration: 0.3) 
     self.body.animationPlayer(forKey: "death")?.play() 
    } 
} 
+0

あなたのソリューションを投稿していただきありがとうございます。私はSCNAnimationPlayer自体がより細かい再生/トランスポートコントロール自体をサポートしていないことに少し失望しています。うまくいけば、それはiOSの将来のバージョンで来るだろう。 – ff10

0

1つの鏡面フレームでアニメーションを停止したいすべての人に適しています。ちなみに、SCNAnimationPlayer.animationtimeOffsetの設定に対応していないのはかなり奇妙です。

+(SCNAnimationPlayer*)animationPlayer:(SCNAnimationPlayer *)animPlayer onTimeOffset:(CGFloat)timeOffset{ 
    SCNAnimation *anim = animPlayer.animation; 
    CAAnimation *caAnim = [CAAnimation animationWithSCNAnimation:anim]; 
    caAnim.timeOffset = timeOffset * caAnim.duration; 
    caAnim.speed = 0; 
    caAnim.usesSceneTimeBase = NO; 
    anim = [SCNAnimation animationWithCAAnimation:caAnim]; 
    animPlayer = [SCNAnimationPlayer animationPlayerWithAnimation:anim]; 
    return animPlayer; 
} 

あなたが進歩の半分にスケ​​ルトンのアニメーションを停止する場合は、0.5にtimeOffsetを設定します。

関連する問題