iOS 18 上的 SceneKit 没有平滑的动画过渡

问题描述 投票:0回答:1

我遇到了 SceneKit 的问题。

我正在开发一款3D手机游戏。我有一个角色 3D 模型和几个骨骼动画 CAAnimation。我以 *.dae 格式从 Maya 导入模型和动画。 角色的动画一个接一个地连续播放,每个新动画都是随机触发的。 通过设置 fadeInDuration 和 fadeOutDuration 属性,可以使动画之间的过渡变得平滑。这是代码示例:

import UIKit import QuartzCore import SceneKit

class TestAnimationController: UIViewController {

var bodyNode: SCNNode?  

override func viewDidLoad() {
    super.viewDidLoad()
    
  let scnView = SCNView(frame: self.view.bounds)
  scnView.backgroundColor = .black // Set your desired background color
  scnView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
  
  let scene = SCNScene(named: "art.scnassets/scene/Base_room/ROOM5.scn")!
  bodyNode = collada2SCNNode(filepath: "art.scnassets/female/girl_body_races.dae")!
  bodyNode?.renderingOrder = 10
  
  scene.rootNode.addChildNode(bodyNode!)

  playIdleAnimation()
  
  scnView.scene = scene // Assign the scene to the SCNView
  self.view.addSubview(scnView) // Add the SCNView to your main view)
}
func collada2SCNNode(filepath:String) -> SCNNode? { if let scene = SCNScene(named: filepath) { let node = scene.rootNode.childNodes[0] return node } else { return nil } }

func playIdleAnimation() {
    let array = [
        "art.scnassets/female/animations/idle/girl_idle_4.dae",
        "art.scnassets/female/animations/idle/girl_idle1.dae",
        "art.scnassets/female/animations/idle/girl_idle2.dae",
        "art.scnassets/female/animations/idle/Girl_idle3.dae",
    ]
    let animation =  CAAnimation.animationWithSceneNamed(array.randomElement() ?? "")!
    self.setAnimationAdd(
      fadeInDuration: 1.0,
      fadeOutDuration: 1.0,
      keyTime: 0.99,
      animation,
      isLooped: false
    ) { [weak self] in
      guard let self = self else { return }
      try? self.playBoringAnimations()
    }
}

func playBoringAnimations() {
    let array = [
        "art.scnassets/female/animations/boring/girl_boring1.dae",
        "art.scnassets/female/animations/boring/girl_boring2.dae",
        "art.scnassets/female/animations/boring/girl_boring3.dae",
        "art.scnassets/female/animations/boring/girl_boring4.dae",
        "art.scnassets/female/animations/boring/girl_boring5.dae",
        "art.scnassets/female/animations/boring/girl_boring6.dae",
        "art.scnassets/female/animations/boring/girl_boring8.dae"
    
    ]
    let animation =  CAAnimation.animationWithSceneNamed(array.randomElement() ?? "")!
    self.setAnimationAdd(
      fadeInDuration: 1.0,
      fadeOutDuration: 1.0,
      keyTime: 0.99,
      animation,
      isLooped: false
    ) { [weak self] in
      guard let self = self else { return }
      try? self.playIdleAnimation()
    }
}


func setAnimationAdd(fadeInDuration : CGFloat, fadeOutDuration : CGFloat, keyTime : CGFloat,  _ animation: CAAnimation, isLooped: Bool, completion: (() -> Void)?) {
    
    animation.fadeInDuration = fadeInDuration
    animation.fadeOutDuration = fadeOutDuration
  
    if !isLooped {
        animation.repeatCount = 1
    } else {
        animation.repeatCount = Float.greatestFiniteMagnitude
    }
    animation.animationEvents = [
        SCNAnimationEvent(keyTime: keyTime, block: { _, _, _ in completion?() })
    ]
    bodyNode?.addAnimation(animation, forKey: "avatarAnimation")
}
}

一切都很完美,直到我更新到 iOS 18。在物理设备上,动画现在突然过渡,没有早期 iOS 版本中出现的平滑混合。它们之间的切换非常明显,就好像 fadeInDuration 和 fadeOutDuration 参数被忽略一样。

但是,在 iOS 18 模拟器中,动画仍然像以前一样平滑过渡。

这里有两个示例视频 - IOS 17.5 和 IOS 18 https://youtube.com/shorts/jzoMRF4skAQ - IOS 17,5 流畅 https://youtube.com/shorts/VJXrZzO9wl0 - IOS 18 不流畅

我在 IOS 17.5 中尝试了这段代码,一切正常

xcode scenekit
1个回答
0
投票

我尝试将 CAanimatiom 对象转换为 SCNanimation。但没有效果。动画现在突然过渡,没有平滑混合。

这是代码

 func setAnimationAddNew(fadeInDuration : CGFloat, fadeOutDuration : CGFloat, keyTime : CGFloat,  _ animation: CAAnimation, isLooped: Bool, completion: (() -> Void)?) {
    
  // Создаем анимационный плеер
  let scnAnimation = SCNAnimation(caAnimation: animation)
  // Создаем анимационный плеер
  let animationPlayer = SCNAnimationPlayer(animation: scnAnimation)
  animationPlayer.blendFactor = 1.0
  // Настраиваем параметры анимации
  animationPlayer.animation.blendInDuration = fadeInDuration
  animationPlayer.animation.blendOutDuration = fadeOutDuration
  
  if !isLooped {
    animationPlayer.animation.repeatCount = 1
  } else {
    animationPlayer.animation.repeatCount = CGFloat.greatestFiniteMagnitude
  }
  animationPlayer.animation.animationEvents = [
      SCNAnimationEvent(keyTime: keyTime, block: { _, _, _ in completion?() })
  ]
  bodyNode?.addAnimationPlayer(animationPlayer, forKey: "avatarAnimation")
  animationPlayer.play()
}
© www.soinside.com 2019 - 2024. All rights reserved.