Использование Scenekit sceneTime для просмотра анимации iOS - PullRequest
0 голосов
/ 01 июня 2018

Я пытаюсь изменить настройки игры Xcode по умолчанию, чтобы я мог: запрограммировать анимацию в геометрию, прокрутить эту анимацию и позволить пользователю воспроизводить анимацию автоматически.

Мне удалось получитьочистка анимации для работы, установив время сцены представления на основе значения скруббера.Однако, когда я устанавливаю логическое значение isPlaying на SCNSceneRenderer в значение true, оно сбрасывает время на 0 в каждом кадре, и я не могу заставить его убрать первый кадр.

Из документов яЯ предполагаю, что это означает, что он не обнаружит мою анимацию, и думает, что продолжительность всех анимаций равна 0.

Вот моя функция viewDidLoad в моем GameViewController:

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

isPlaying:

https://developer.apple.com/documentation/scenekit/scnscenerenderer/1523401-isplaying

связанный вопрос:

SceneKit SCNSceneRendererDelegate - функция визуализации не вызывается

Ответы [ 2 ]

0 голосов
/ 23 июля 2018

sceneTime автоматически устанавливается равным 0.0 после запуска действий и анимации для каждого кадра.

Использование может использовать метод делегирования рендерера (_: updateAtTime :), чтобы установить для sceneTime необходимое значение, прежде чем SceneKit запустит действия и анимации..

Сделайте так, чтобы GameViewController соответствовал SCNSceneRendererDelegate:

class GameViewController: UIViewController, SCNSceneRendererDelegate {
    // ...
}

Убедитесь, что вы держите scnView.delegate = self внутри viewDidLoad ().

Теперь реализуйте рендер (_: updateAtTime :) внутриваш класс GameViewController:

// 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!
}
0 голосов
/ 06 июня 2018

Я не мог заставить его работать элегантным образом, но я исправил это, добавив этот вызов 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)
}

Я уверен, что есть лучшее решение, но это работает.

...