, Отличный обходной путь, однако, естественное поведение Apple должно быть изменено. Спасибо за это, серьезно. Имели эту проблему на некоторое время

ая проблема:

Я добавляю этот раздел ПОСЛЕ разъяснения проблемы. - Я могу приостановить видео (я не хочу, чтобы оно воспроизводилось по циклу). Когда мой узел попадает в поле зрения, он воспроизводит мое видео, даже если оно находится в режиме паузы. Если воспроизведение моего видео закончилось и оно появляется, оно перезапустится. Я хочу, чтобы удалить это поведение.

В моем приложении у меня есть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-й абзац, чтобы увидеть используемые переменные). Просто ищите, чтобы удалить «действие» узла, играющего каждый раз, когда он виден.

Сложение:

Ради того, чтобы следить за созданием моего видео плеера, если интересно, вот оно. Дайте мне знать, если есть что-то еще, что вы хотели бы увидеть (не уверен, что еще вы хотели бы увидеть), и спасибо за вашу помощь.

func createVideoNode(_ anchor:ARImageAnchor, initialPOV:SCNNode) -> My3DPlayer? {

    guard let currentFrame = self.sceneView.session.currentFrame else {
        return nil
    }

    let delegate = UIApplication.shared.delegate as! AppDelegate

    var videoPlayer:My3DPlayer!
    videoPlayer = delegate.testing ? My3DPlayer(data: nil, currentFrame: currentFrame, anchor: anchor) : My3DPlayer(data: self.urlData, currentFrame: currentFrame, anchor: anchor)

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

    return videoPlayer
}

My3dPlayer Class:

class My3DPlayer: SCNNode {

    init(geometry: SCNGeometry?) {
        super.init()
        self.geometry = geometry
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    convenience init(data:Data?, currentFrame:ARFrame, anchor:ARImageAnchor) {
        self.init(geometry: nil)
        self.createPlayer(currentFrame, data, anchor)
    }

    private func createPlayer(_ frame:ARFrame, _ data:Data?,_ anchor:ARImageAnchor) {

        let physicalSize = anchor.referenceImage.physicalSize

        print("Init Player W/ physicalSize: \(physicalSize)")

        //Create video
        if((UIApplication.shared.delegate! as! AppDelegate).testing) {
            let path = Bundle.main.path(forResource: "Bear", ofType: "mov")
            self.url = URL(fileURLWithPath: path!)
        }
        else {
            let url = data!.getAVAssetURL(location: "MyLocation")
            self.url = url
        }
        let asset = AVAsset(url: self.url)
        let track = asset.tracks(withMediaType: AVMediaType.video).first!
        let playerItem = AVPlayerItem(asset: asset)
        let player = AVPlayer(playerItem: playerItem)
        self.player = player
        var videoSize = track.naturalSize.applying(track.preferredTransform)

        videoSize = CGSize(width: abs(videoSize.width), height: abs(videoSize.height))
        print("Init Video W/ size: \(videoSize)")

        //Determine if landscape or portrait
        self.landscape = videoSize.width > videoSize.height
        print(self.landscape == true ? "Landscape" : "Portrait")

        //Do something when video ended
        NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying(note:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)

        //Add observer to determine when Player is ready
        player.addObserver(self, forKeyPath: "status", options: [], context: nil)

        //Create video Node
        let videoNode = SKVideoNode(avPlayer: player)

        //Create 2d scene to put 2d player on - SKScene
        videoNode.position = CGPoint(x: videoSize.width/2, y: videoSize.height/2)
        videoNode.size = videoSize


        //Portrait -- //Landscape doesn't need adjustments??
        if(!self.landscape) {
            let width = videoNode.size.width
            videoNode.size.width = videoNode.size.height
            videoNode.size.height = width
            videoNode.position = CGPoint(x: videoNode.size.width/2, y: videoNode.size.height/2)
        }

        let scene = SKScene(size: videoNode.size)

        //Add videoNode to scene
        scene.addChild(videoNode)

        //Create Button-look even though we don't use the button. Just creates the illusion to pressing play and pause
        let image = UIImage(named: "PlayButton")!
        let texture = SKTexture(image: image)
        self.button = SKSpriteNode(texture: texture)
        self.button.position = videoNode.position

        //Makes the button look like a square
        let minimumSize = [videoSize.width, videoSize.height].min()!
        self.button.size = CGSize(width: minimumSize/4, height: minimumSize/4)
        scene.addChild(button)

        //Get ratio difference from physicalsize and video size
        let widthRatio = Float(physicalSize.width)/Float(videoSize.width)
        let heightRatio = Float(physicalSize.height)/Float(videoSize.height)

        let finalRatio = [widthRatio, heightRatio].min()!

        //Create a Plane (SCNPlane) to put the SKScene on
        let plane = SCNPlane(width: scene.size.width, height: scene.size.height)
        plane.firstMaterial?.diffuse.contents = scene
        plane.firstMaterial?.isDoubleSided = true

        //Set Self.geometry = plane
        self.geometry = plane

        //Size the node correctly
        //Find the real scaling variable
        let scale = CGFloat(finalRatio)
        let appearanceAction = SCNAction.scale(to: scale, duration: 0.4)
        appearanceAction.timingMode = .easeOut

        //Set initial scale to 0 then use action to scale up
        self.scale = SCNVector3Make(0, 0, 0)
        self.runAction(appearanceAction)
    }

    @objc func playerDidFinishPlaying(note: Notification) {
        self.player.seek(to: .zero, toleranceBefore: .zero, toleranceAfter: .zero)
        self.player.seek(to: .zero, toleranceBefore: .zero, toleranceAfter: .zero)
        self.setButtonAlpha(alpha: 1)
    }
}

Efforts1:

Я пытался остановить отслеживание с помощью:

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

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

    createVideoNode(imageAnchor)
    self.resetConfiguration(turnOnConfig: true, turnOnImageTracking: false)   
}

func resetConfiguration(turnOnConfig: Bool = true, turnOnImageTracking:Bool = false) {
    let configuration = ARWorldTrackingConfiguration()
    if(turnOnImageTracking) {
        guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else {
            fatalError("Missing expected asset catalog resources.")
        }
        configuration.planeDetection = .horizontal
        configuration.detectionImages = referenceImages
    }
    else {
        configuration.planeDetection = []
    }
    if(turnOnConfig) {
        sceneView.session.run(configuration, options: [.resetTracking])
    }
}

Выше я попытался сбросить конфигурацию. Это только заставляет его сбрасывать плоскости, которые кажутся, так как видео все еще воспроизводится при рендере. Будет ли он приостановлен или закончен, он будет сброшен и начнется сначала или продолжит воспроизведение там, где остановился.

Efforts2:

я пытался

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

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

    createVideoNode(imageAnchor)
    self.pauseTracking()  
}

func pauseTracking() {
    self.sceneView.session.pause()
}

Это останавливает все, поэтому камера даже зависает, так как ничего не отслеживается. Это совершенно бесполезно здесь.

Ответы на вопрос(1)

Ваш ответ на вопрос