带有 AVCaptureSession 的 Unity Vuforia 扩展 EXC_BAD_ACCESS

Unity Vuforia Extension EXC_BAD_ACCESS with AVCaptureSession

所以我将 Unity 2017.2.0f3 与 Vuforia Extension 一起使用,并且我按照 https://github.com/blitzagency/ios-unity5 教程将项目导入现有的 iOS 项目中。现存的 iOS 项目包括一个视图,您可以在其中切换使用 Vuforia 的 AR 视图和可以扫描条形码的本机 iOS AVCaptureSession。前者可以正常工作,但是一旦我尝试执行 session.addInputsession.addOutput 后一个功能就会崩溃:

EXC_BAD_ACCESS

com.apple.avfoundation.videodataoutput.bufferqueue 队列中。 我尝试使用 NSZombie 来了解更多有关尝试发送消息的对象类型的信息,但我只能 运行 物理设备上的应用程序,因此我无法了解有关它的实际对象的更多信息尝试向其发送导致崩溃的消息。

我的理由是,这可能与 Vuforia 坚持引用释放的 VIdeoDataOutput 缓冲区队列有关,这是由我创建一个新的 AVCaptureSession 触发的,其中包含 AVCaptureOutputAVCaptureInput。棘手的是,我不知道如何真正确定这一点,因为它是第三方图书馆。唯一具有 Objective-C 包装器的 ViewController 称为 CameraCapture.mm 但这似乎是一个退化的仅 Unity View Controller,因为我在该方法中放置的任何 NSLogs 或断点是没有叫。

private func setupCamera() {
    guard let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo),
        let input = try? AVCaptureDeviceInput(device: device) else {
            return
    }

    if session.canAddInput(input) {
        session.addInputWithNoConnections(input)
    }

    previewLayer = AVCaptureVideoPreviewLayer(session: session)
    previewLayer.frame = self.view.bounds
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
    view.layer.addSublayer(previewLayer)
    cameraPreviewView.layer.addSublayer(previewLayer)
    let metadataOutput = AVCaptureMetadataOutput()

    if session.canAddOutput(metadataOutput) {
        session.addOutputWithNoConnections(metadataOutput)

        metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        metadataOutput.metadataObjectTypes = metadataOutput.availableMetadataObjectTypes
    } else {
        print("Could not add metadata output")
    }
}

一旦调用上述方法,即使在从 blitz 教程 appDelegate.stopUnity() 调用 AppDelegate 函数后,应用程序总是会崩溃。

所以基本上我得到的错误是 Unity 在后台时没有真正退出。这是一个可配置的设置,用于 Unity 本身的 iOS Unity 导出。如果您转到“编辑”>“播放器设置”>,然后在 其他设置 右侧的检查器中,有一个名为 后台行为 的字段。我的原始导出将此设置为 Suspend,这导致 Unity/Vuforia 中相机固有的 AVCaptureSession 可能不会被清理,就其 videoOutput 委托缓冲区而言,当 Unity不是 运行,因此当我认为我停止了 Unity 并开始新的 AVCaptureSession 时,结果是 EXC_BAD_ACCESS。因此,通过将 Behavior In Background 切换为 Exit 然后在我的应用程序中保证我在设置 [=27 之前调用了 appDelegate.stopUnity() =] 对新 AVCaptureSession() 成功解决了问题。