Swift获取已放置SCNNode的世界坐标(x,y,z)并定位球体至平面中心
解决ARPlane中心生成独立球体的坐标问题
我明白你的需求:要在AR平面的中心生成一个球体,而且不能把球体作为平面节点的子节点。之前的问题出在坐标空间的混淆上,咱们一步步来解决。
问题根源
你传递给loadSphere的x/y/z是planeAnchor.center的坐标,但这个坐标是相对于AR锚点节点(也就是didAdd方法里的node参数)的本地坐标,不是世界空间坐标。当你直接把这个值设置给球体的position(默认相对于根节点,也就是世界空间),自然会出现在错误的位置,甚至是(0,0,0)。
正确解决方案
方法1:直接获取平面节点的世界空间中心
在创建平面节点后,直接用它的worldPosition属性拿到世界空间的中心坐标,这是最直接的方式:
修改renderer(_:didAdd:for:)方法:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { guard let planeAnchor = anchor as? ARPlaneAnchor else { return } let width = CGFloat(planeAnchor.extent.x) let height = CGFloat(planeAnchor.extent.z) let plane = SCNPlane(width: width, height: height) plane.materials.first?.diffuse.contents = UIColor.orange let planeNode = SCNNode(geometry: plane) // planeAnchor.center是锚点节点的本地坐标,设置给planeNode的本地position是正确的 let localCenter = SCNVector3(planeAnchor.center.x, planeAnchor.center.y, planeAnchor.center.z) planeNode.position = localCenter planeNode.eulerAngles.x = -.pi / 2 node.addChildNode(planeNode) node.name = "plane" // 获取平面节点的世界空间中心坐标 let planeWorldCenter = planeNode.worldPosition loadSphere(worldCenter: planeWorldCenter) }
然后调整loadSphere函数,直接接收世界空间坐标:
func loadSphere(worldCenter: SCNVector3) { guard let idleScene = SCNScene(named: "art.scnassets/bounceFixed.dae") else { print("无法加载球体模型") return } let sphereNode = SCNNode() for child in idleScene.rootNode.childNodes { sphereNode.addChildNode(child) } sphereNode.name = "Sphere" // 直接设置世界空间位置 sphereNode.position = worldCenter sphereNode.scale = SCNVector3(0.001, 0.001, 0.001) // 务必将球体添加到根节点,确保坐标基于世界空间 sceneView.scene.rootNode.addChildNode(sphereNode) }
方法2:手动转换本地坐标到世界空间
如果你想保留传递planeAnchor.center的逻辑,可以通过锚点节点的坐标转换方法,把本地坐标转成世界坐标:
// 在didAdd方法中替换坐标传递的代码 let localCenter = SCNVector3(planeAnchor.center.x, planeAnchor.center.y, planeAnchor.center.z) // 将锚点本地坐标转换为世界空间坐标(to: nil表示转换到根节点/世界空间) let worldCenter = node.convertPosition(localCenter, to: nil) loadSphere(worldCenter: worldCenter)
为什么之前的尝试出错?
- 你用
sceneView.scene.rootNode.childNodes[3].worldPosition大概率是找错了节点(比如选中了相机或其他无关节点); node.worldPosition是AR锚点节点的位置,不是平面的中心位置——平面节点的position是相对于锚点节点的本地坐标,所以需要通过planeNode.worldPosition才能拿到平面的真实世界中心。
内容的提问来源于stack exchange,提问作者user287474
相关产品推荐
相关产品推荐

