[英]Using Scenekit sceneTime to scrub through animations iOS
我試圖修改Xcode的默認游戲設置,以便能夠:將動畫編程到幾何圖形中,通過動畫進行擦洗,然后讓用戶自動播放動畫。
通過基於清理器的值設置視圖的場景時間,我設法使動畫的清理工作了。 但是,當我將SCNSceneRenderer上的isPlaying布爾值設置為true時,它將每幀的時間重置為0,而我無法使它移出第一幀。
從文檔中,我假設這意味着它不會檢測到我的動畫,並認為所有動畫的持續時間均為0。
這是我的GameViewController中的viewDidLoad函數:
override func viewDidLoad() {
super.viewDidLoad()
// create a new scene
let scene = SCNScene(named: "art.scnassets/ship.scn")!
// create and add a camera to the scene
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
// place the camera
cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
// create and add a light to the scene
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = .omni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
scene.rootNode.addChildNode(lightNode)
// create and add an ambient light to the scene
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = .ambient
ambientLightNode.light!.color = UIColor.darkGray
scene.rootNode.addChildNode(ambientLightNode)
// retrieve the ship node
let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!
// define the animation
//ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1)))
let positionAnimation = CAKeyframeAnimation(keyPath: "position.y")
positionAnimation.values = [0, 2, -2, 0]
positionAnimation.keyTimes = [0, 1, 3, 4]
positionAnimation.duration = 5
positionAnimation.usesSceneTimeBase = true
// retrieve the SCNView
let scnView = self.view as! SCNView
scnView.delegate = self
// add the animation
ship.addAnimation(positionAnimation, forKey: "position.y")
// set the scene to the view
scnView.scene = scene
// allows the user to manipulate the camera
scnView.allowsCameraControl = true
// show statistics such as fps and timing information
scnView.showsStatistics = true
// configure the view
scnView.backgroundColor = UIColor.black
// add a tap gesture recognizer
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
scnView.addGestureRecognizer(tapGesture)
// play the scene
scnView.isPlaying = true
//scnView.loops = true
}
任何幫助表示贊賞! :)
參考文獻:
sceneTime:
https://developer.apple.com/documentation/scenekit/scnscenerenderer/1522680-scenetime
正在玩:
https://developer.apple.com/documentation/scenekit/scnscenerenderer/1523401-isplaying
相關問題:
我無法使其以一種優雅的方式工作,但我通過添加以下Timer調用對其進行了修復:
Timer.scheduledTimer(timeInterval: timeIncrement, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
timeIncrement是一個Double設置為0.01,updateTimer是以下函數:
// helper function updateTimer
@objc func updateTimer() {
let scnView = self.view.subviews[0] as! SCNView
scnView.sceneTime += Double(timeIncrement)
}
我敢肯定有更好的解決方案,但是可以。
在每幀上運行動作和動畫后,sceneTime將自動設置為0.0。
在SceneKit運行動作和動畫之前,可以使用renderer(_:updateAtTime :)委托方法將sceneTime設置為所需的值。
使GameViewController符合SCNSceneRendererDelegate:
class GameViewController: UIViewController, SCNSceneRendererDelegate {
// ...
}
確保在viewDidLoad()中保留scnView.delegate = self
。
現在在您的GameViewController類中實現renderer(_:updateAtTime :):
// need to remember scene start time in order to calculate current scene time
var sceneStartTime: TimeInterval? = nil
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
// if startTime is nil assign time to it
sceneStartTime = sceneStartTime ?? time
// make scene time equal to the current time
let scnView = self.view as! SCNView
scnView.sceneTime = time - sceneStartTime!
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.