swift 如何解决场景套件渲染器“EXC_BAD_ACCESS(代码=1,地址= 0xf00000010a10c10)"?

vbkedwbf  于 2023-03-11  发布在  Swift
关注(0)|答案(5)|浏览(131)

这是我得到的错误,检查所附的图片获取更多信息.
网站。苹果。场景工具包。scnview渲染器(17):异常错误访问(代码=1,地址= 0xf 00000010 a10 c10)
以下是错误日志:

当我调用下面的函数时,我可以重现这个错误,但只有当这个函数在一秒钟内被调用很多次时。如果用户快速点击按钮循环到下一个可用的汽车,就会发生这种情况。
如您所见,我尝试将其 Package 在DispatchQueue中以解决问题。
您还将注意到,我创建了一个Bool alreadyCyclingCars来跟踪cycleCarNext()函数在允许再次调用之前是否已完成。
此函数实际上迭代unlockedCars数组中的所有unlockedCars
如果车的类型与我们正在寻找的车匹配,我就中断循环。
然后我们确定当前汽车的索引,看看我需要显示的下一辆汽车是否是数组中的下一辆汽车(如果有)。如果不是,我们已经到达了数组的末尾,所以我显示数组中的第一辆汽车。

还有人比我更了解这个吗?真的很感激,谢谢!

func cycleCarNext() {
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            if !self.alreadyCyclingCars {
                self.alreadyCyclingCars = true
                var indexOfCurrentCar = 0
                for (index, car) in UserData.shared.unlockedCars.enumerated() {
                    if car.type == self.overlayScene.currentCarOnDisplay {
                        indexOfCurrentCar = index
                        break
                    }
                }

                if indexOfCurrentCar < UserData.shared.unlockedCars.count - 1 {
                    let nextCar = UserData.shared.unlockedCars[indexOfCurrentCar+1]
                    self.playerNode.removeFromParentNode()
                    self.playerNode = nextCar
                    self.playerNode.name = "player"
                    self.playerNode.position = SCNVector3(x: 17, y: 0.3, z: 0)
                    self.playerNode.eulerAngles = SCNVector3(x: 0, y: toRadians(angle: 45),z: 0)
                    self.scene.rootNode.addChildNode(self.playerNode)
                    self.overlayScene.currentCarOnDisplay = nextCar.type
                    self.overlayScene.updateGarageInterface()
                } else {
                    guard let nextCar = UserData.shared.unlockedCars.first else { return }
                    self.playerNode.removeFromParentNode()
                    self.playerNode = nextCar
                    self.playerNode.name = "player"
                    self.playerNode.position = SCNVector3(x: 17, y: 0.3, z: 0)
                    self.playerNode.eulerAngles = SCNVector3(x: 0, y: toRadians(angle: 45),z: 0)
                    self.scene.rootNode.addChildNode(self.playerNode)
                    self.overlayScene.currentCarOnDisplay = nextCar.type
                    self.overlayScene.updateGarageInterface()
                }
                self.alreadyCyclingCars = false
            }
        }
    }
wz8daaqr

wz8daaqr1#

根据我的经验,当您尝试在SCNSceneRendererDelegate委托方法之外修改SceneKit的场景图(添加/删除节点等)时,会发生此类错误。
假设您有一个线程以60 fps的速度执行渲染,而另一个线程(例如:主线程),从要渲染的对象中删除节点。在某个点上,当正在渲染的对象被另一个线程删除时,渲染线程将在渲染过程中进行部分操作。这就是EXC_BAD_ACCESS发生的时候。场景修改的次数越多,您就越有可能看到这种冲突,因此按钮混搭更容易重现该问题。
修正是只在SCNSceneRendererDelegate代理方法中修改你的场景。我会尝试类似...

func cycleCarNext() {
    self.cycleNextCar = true
}

func renderer(renderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval) {
    if (self.cycleNextCar) {
        self.doCycleNextCar()
        self.cycleNextCar = false
    }
}

func doCycleNextCar() {
    var indexOfCurrentCar = 0
    for (index, car) in UserData.shared.unlockedCars.enumerated() {
        if car.type == self.overlayScene.currentCarOnDisplay {
            indexOfCurrentCar = index
            break
        }
    }

    if indexOfCurrentCar < UserData.shared.unlockedCars.count - 1 {
        let nextCar = UserData.shared.unlockedCars[indexOfCurrentCar+1]
        self.playerNode.removeFromParentNode()
        self.playerNode = nextCar
        self.playerNode.name = "player"
        self.playerNode.position = SCNVector3(x: 17, y: 0.3, z: 0)
        self.playerNode.eulerAngles = SCNVector3(x: 0, y: toRadians(angle: 45),z: 0)
        self.scene.rootNode.addChildNode(self.playerNode)
        self.overlayScene.currentCarOnDisplay = nextCar.type
        self.overlayScene.updateGarageInterface()
    } else {
        guard let nextCar = UserData.shared.unlockedCars.first else { return }
        self.playerNode.removeFromParentNode()
        self.playerNode = nextCar
        self.playerNode.name = "player"
        self.playerNode.position = SCNVector3(x: 17, y: 0.3, z: 0)
        self.playerNode.eulerAngles = SCNVector3(x: 0, y: toRadians(angle: 45),z: 0)
        self.scene.rootNode.addChildNode(self.playerNode)
        self.overlayScene.currentCarOnDisplay = nextCar.type
        self.overlayScene.updateGarageInterface()
    }
}

cycleCarNext将由您的主线程调用,因为它目前是。您可能需要设置SCNView的委托的地方了(例如;sceneView.delegate = self
其思想是,当cycleCarNext布尔值在主线程中立即设置时,场景不会发生变化,而是在SceneKit渲染循环中的正确时间/线程发生变化。

b4qexyjb

b4qexyjb2#

面对同样的问题,并找出了这个崩溃造成的personSegmentationWithDepth的设备与LiDAR

if ARWorldTrackingConfiguration.supportsFrameSemantics(.personSegmentationWithDepth) {
    configuration.frameSemantics.insert(.personSegmentationWithDepth)
}
vshtjzan

vshtjzan3#

我已经为这个错误纠结了一段时间了,我只是想添加一个注解,以防它对使用SCNRenderer的任何人有帮助,这就是我使用的

.render(withViewport:commandBuffer:passDescriptor:)

但这不会调用委托呈现方法。

.render(atTime:viewport:commandBuffer:passDescriptor:)

即使您没有使用时间间隔参数,然后将调用代理方法renderer(_:updateAtTime:),您可以在其中安全地进行场景更新。

ilmyapht

ilmyapht4#

如果在您的方案中启用了“GPU帧捕获”,禁用它将修复此问题:
在Xcode中转到您当前的方案-〉选择编辑方案... -〉运行/选项:将“GPU帧捕获”设置为禁用。
取自here

pepwfjgg

pepwfjgg5#

也许你没有初始化对象,它看起来在分配之前就呈现了。你可以使用awakeFromNib方法来修复这个问题。

override func awakeFromNib() {
    super.awakeFromNib()
    createScene()
}

相关问题