解決したいこと
ARKitを使用し、トラッキングした画像の上に動画を再生します。
画像からトラッキングが外れた時でも動画が再生され続け、音も流れっぱなしなので一時停止したいです。
やったこと
下記コードにより、トラッキングが外れた際に動画の一時停止を実現しようと試みました。
しかし、画像をトラッキングした瞬間にアプリが落ちてしまいます。
原因がわかりません。
swift
1 func session(_ session: ARSession, didUpdate frame: ARFrame) { 2 if !sceneView.isNode(videoHolder!, insideFrustumOf: sceneView!.pointOfView!) { 3 videoPlayerNode?.pause() 4 } 5 }
全体のコード
swift
1import UIKit 2import SceneKit 3import ARKit 4import SafariServices 5import AVFoundation 6 7class ViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate { 8 @IBOutlet var sceneView: ARSCNView! 9 10 let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: Bundle.main) 11 12 13 override func viewDidLoad() { 14 super.viewDidLoad() 15 16 let scene = SCNScene() 17 sceneView.scene = scene 18 } 19 20 21 override func viewWillAppear(_ animated: Bool) { 22 super.viewWillAppear(animated) 23 24 let configuration = ARImageTrackingConfiguration() 25 26 configuration.trackingImages = referenceImages! 27 28 sceneView.session.run(configuration) 29 30 } 31 32 var videoHolder: SCNNode? 33 34 35 func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { 36 37 guard let imageAnchor = anchor as? ARImageAnchor else { return } 38 39 let referenceImage = imageAnchor.referenceImage 40 41 let width = CGFloat(referenceImage.physicalSize.width) 42 let height = CGFloat(referenceImage.physicalSize.height) 43 44 let videoHolderGeometry = SCNPlane(width: width, height: height) 45 46 videoHolder!.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0) 47 48 videoHolder!.geometry = videoHolderGeometry 49 50 if let videoURL = Bundle.main.url(forResource: "img.scnassets/route", withExtension: "MOV"){ 51 setupVideoOnNode(videoHolder!, fromURL: videoURL) 52 } 53 54 55 node.addChildNode(videoHolder!) 56 57 videoHolder!.name = "route" 58 } 59 60 61 var videoPlayerNode: SKVideoNode? 62 var videoPlayer: AVPlayer? 63 64 65 func setupVideoOnNode(_ node: SCNNode, fromURL url: URL){ 66 67 let videoPlayer = AVPlayer(url: url) 68 69 videoPlayerNode = SKVideoNode(avPlayer: videoPlayer) 70 videoPlayerNode?.yScale = -1 71 72 73 let spriteKitScene = SKScene(size: CGSize(width: 1000, height: 1000)) 74 spriteKitScene.scaleMode = .aspectFit 75 videoPlayerNode?.position = CGPoint(x: spriteKitScene.size.width/2, y: spriteKitScene.size.height/2) 76 videoPlayerNode?.size = spriteKitScene.size 77 spriteKitScene.addChild(videoPlayerNode!) 78 79 80 node.geometry?.firstMaterial?.diffuse.contents = spriteKitScene 81 82 83 videoPlayerNode?.play() 84 videoPlayer.volume = 100 85 86 //ループ再生 87 videoPlayer.actionAtItemEnd = AVPlayer.ActionAtItemEnd.none; 88 NotificationCenter.default.addObserver(self, 89 selector: #selector(self.stateEnd), 90 name: NSNotification.Name("AVPlayerItemDidPlayToEndTimeNotification"), 91 object: videoPlayer.currentItem) 92 93 } 94 95 96 @objc func stateEnd(notification: NSNotification) { 97 let avPlayerItem = notification.object as? AVPlayerItem 98 avPlayerItem?.seek(to: CMTime.zero) 99 } 100 101 102 func session(_ session: ARSession, didUpdate frame: ARFrame) { 103 if !sceneView.isNode(videoHolder!, insideFrustumOf: sceneView!.pointOfView!) { 104 videoPlayerNode?.pause() 105 } 106 } 107 108 // 画面に表示された直後に呼ばれる。 109 override func viewWillDisappear(_ animated: Bool) { 110 super.viewWillDisappear(animated) 111 sceneView.session.pause() 112 } 113 114 115 116 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 117 guard let location = touches.first?.location(in: sceneView), 118 let result = sceneView.hitTest(location, options: nil).first else { 119 return 120 } 121 let node = result.node 122 123 if node.name == "route" { 124 let safariVC = SFSafariViewController(url: URL(string: "https://images.google.com/?gws_rd=ssl")!) 125 self.present(safariVC, animated: true, completion: nil) 126 } 127 } 128 129 130} 131
以上です。よろしくお願いいたします!
あなたの回答
tips
プレビュー