ARKit中render方法内节点无法缩放或旋转问题咨询
解决ARKit中
renderer(_:nodeFor:)设置节点缩放旋转无效的问题 这个问题我做ARKit项目时也踩过一模一样的坑,核心原因是ARKit对renderer(_:nodeFor:)返回节点的管理机制导致的,咱们一步步拆解清楚:
为什么你的设置完全无效?
当你在renderer(_:nodeFor:)里返回一个SCNNode给ARKit后,ARKit会自动把这个节点和对应的ARAnchor绑定,并且会直接覆盖你设置的缩放、旋转属性——因为ARKit需要根据锚点(Anchor)的实时跟踪结果,动态更新节点的空间变换(位置、姿态),它会直接修改节点的transform矩阵,而这个矩阵会覆盖你单独设置的scale和eulerAngles。
另外还有个容易忽略的小细节:你代码里写的eulerAngles.x = -90是角度值,但SceneKit的旋转属性用的是弧度,这也会导致旋转设置看起来完全没效果,正确的-90度应该写成-.pi / 2。
两种可行的解决方案
方案1:用容器节点包裹模型节点
创建一个空的容器节点,把你的模型节点作为容器的子节点,然后返回容器节点给ARKit。这样ARKit只会管理容器节点的变换,模型节点的缩放、旋转是相对容器的,不会被覆盖:
extension RecordPlaceViewController: ARSCNViewDelegate { func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? { guard anchor.name == "test", let sceneModel = SCNScene(named: "assetsmodels.scnassets/phone2.scn"), let nodeModel = sceneModel.rootNode.childNode(withName: "Plane", recursively: true) else { return nil } // 设置材质 nodeModel.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "uv2") // 设置模型的缩放和旋转(注意用弧度) nodeModel.scale = SCNVector3(0.1, 0.1, 0.1) nodeModel.eulerAngles.x = -.pi / 2 // 创建容器节点,把模型加进去 let containerNode = SCNNode() containerNode.addChildNode(nodeModel) return containerNode } }
方案2:在renderer(_:didAdd:for:)中设置变换
改用renderer(_:didAdd:for:)方法,这个方法是ARKit已经把锚点对应的节点添加到场景后调用的,此时ARKit已经完成了初始的变换设置,你再修改节点的属性就不会被覆盖了:
extension RecordPlaceViewController: ARSCNViewDelegate { func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { guard anchor.name == "test", let sceneModel = SCNScene(named: "assetsmodels.scnassets/phone2.scn"), let nodeModel = sceneModel.rootNode.childNode(withName: "Plane", recursively: true) else { return } nodeModel.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "uv2") nodeModel.scale = SCNVector3(0.1, 0.1, 0.1) nodeModel.eulerAngles.x = -.pi / 2 // 把模型节点添加到ARKit创建的节点下 node.addChildNode(nodeModel) } }
总结
两种方案本质都是避免让ARKit直接管理你需要自定义变换的模型节点:要么用容器隔离,要么在ARKit完成初始绑定后再修改属性。另外一定要记住SceneKit的旋转单位是弧度,别再用角度值啦~
内容的提问来源于stack exchange,提问作者mcfly
相关产品推荐
相关产品推荐

