ARKit SKVideoNode играет на рендере

В моем приложении у меня есть SKVideoNode создан из AVPlayer(:URL) внутри 3D Space используя SCNNode объекты и SCNGeometry объекты. я использую ARKit.ImageTracking определить, когда определенное изображение найдено, и воспроизвести видео оттуда. Все хорошо и здорово, за исключением того, что игрок решает играть в свое время, каждый раз, когда AVPlayer появляется в поле зрения; Тем не менее, это может быть всякий раз, когда ARImageAnchor SCNNode прилагается к появляется в поле зрения. В любом случае, AVPlayer играет каждый раз, когда узел попадает в поле зрения объектива камеры. я использую

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if(keyPath == "rate") {
        print((object as! AVPlayer).rate)
    }
}

распечатать курс, и это 1, однако, это было 0.

Я распечатал какую-то функцию печати print("Play") для всех моих функций, использующих player.pause() или player.play(), и ни одна из них не вызывается при изменении ставки выше. Как я могу найти источник того, что меняет ставку моего игрока?

Я проверил оригинальный rootnode, self.sceneview.scene.rootNode.childNodes чтобы убедиться, что я не создаю дополнительные VideoNodes/SCNNodes/AVPlayers и т. д., и кажется, что есть только 1.

Любые идеи о том, почему SKVideoNode/AVPlayer играет, когда SCNNode попадает в поле зрения камеры с помощью ARKit? Заранее спасибо!

Edit1:

Сделан обходной путь, чтобы определить ТОЛЬКО, когда пользователь нажал на этот узел

let tap = UITapGestureRecognizer(target: self, action: #selector(self!.tapGesture))
tap.delegate = self!
tap.name = "MyTap"
self!.sceneView.addGestureRecognizer(tap)

а затем внутри этой следующей функции, я положил

@objc func tapGesture(_ gesture:UITapGestureRecognizer) {
    let tappedNodes = self.sceneView.hitTest(gesture.location(in: gesture.view), options: [SCNHitTestOption.searchMode: 1])

    if !tappedNodes.isEmpty {
        for nodes in tappedNodes {
            if nodes.node == videoPlayer3D {
                videoPlayer3D.tappedVideoPlayer = true
                videoPlayer3D.playOrPause()
                break
            }
        }
    }
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if(keyPath == "rate") {
        print((object as! AVPlayer).rate)
        if(!self.tappedVideoPlayer) {
            self.player.pause() //HERE
        }
    }
}

где videoPlayer3D является SCNNode который содержит SKVideoNode.

Однако я получаю ошибку com.apple.scenekit.scnview-renderer (17): EXC_BAD_ACCESS (code=2, address=0x16d8f7ad0) в разделе "ЗДЕСЬ" выше. Кажется, что средство визуализации сцены пытается изменить мой видео узел в функции рендеринга, хотя я даже не использую renderer(updateAtTime:) функция, я использую только

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

    guard let imageAnchor = anchor as? ARImageAnchor else { return }

    createVideoNode(imageAnchor)

}

определить, когда я вижу изображение, т. е. imageTracking и я создаю узел. Какие-нибудь советы?

Мысль 1

Представлено сообщение об ошибке, в котором говорится, что из объекта SCNView вызывается какой-то метод для средства визуализации методов (это я понимаю из ошибки), но у меня нет специально вызванного узла. Я думаю, что, возможно, вызывается действие по умолчанию, когда узел просматривается, но я не уверен на 100%, как получить к нему доступ или определить, какой метод. Используемые мной объекты не являются объектами SCNView, и я не верю, что они наследуются от объектов SCNView (посмотрите на 1-й абзац, чтобы увидеть используемые переменные). Просто ищите, чтобы удалить "действие" узла, играющего каждый раз, когда он виден.

0 ответов

Хорошо. Итак, это исправление. увидеть renderer(_:updateAtTime:),

var player: AVPlayer!
var play = true

@objc func tap(_ recognizer: UITapGestureRecognizer){
    if play{
        play = false
        player.pause()
    }else{
        play = true
        player.play()
    }
}

func setVideo() -> SKScene{
    let size = CGSize(width: 500, height: 500)
    let skScene = SKScene(size: size)

    let videoURL = Bundle.main.url(forResource: "video.mp4", withExtension: nil)!
    player = AVPlayer(url: videoURL)

    skScene.scaleMode = .aspectFit

    videoSpriteNode = SKVideoNode(avPlayer: player)
    videoSpriteNode.position = CGPoint(x: size.width/2, y: size.height/2)
    videoSpriteNode.size = size
    videoSpriteNode.yScale = -1
    skScene.addChild(videoSpriteNode)

    player.play()

    return skScene
}

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    if let image = anchor as? ARImageAnchor{
        print("found")

        let planeGeometry = SCNPlane(width: image.referenceImage.physicalSize.width, height: image.referenceImage.physicalSize.height)
        let plane = SCNNode(geometry: planeGeometry)
        planeGeometry.materials.first?.diffuse.contents = setVideo()

        plane.transform = SCNMatrix4MakeRotation(-.pi/2, 1, 0, 0)

        node.addChildNode(plane)
    }
}

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    if !play{
        player.pause()
    }
}

Используйте эту идею в своем коде.

Другие вопросы по тегам