如何获取SceneKit中节点旋转后的位置?
解决SceneKit节点旋转后获取末端位置并让第二个节点跟随的问题
这问题我太熟了!你遇到的情况其实是对SceneKit节点position属性的误解——咱们一步步拆解:
为什么position/worldPosition/presentation.position数值一致?
节点的position本质是其锚点的位置,默认情况下SCNNode的锚点位于几何体的中心。你用的SCNBox(width: 0, height: 0, length: 0.02)相当于一条沿z轴的线段,锚点就在这条线段的中点。
当你旋转节点时,旋转是围绕锚点进行的,锚点本身的位置(不管是局部坐标系还是世界坐标系)根本不会改变。所以这三个属性自然会输出同一个值——它们描述的都是锚点的位置,而非几何体上其他点的位置。
正确获取旋转后目标点的方法
你真正需要的是第一个节点几何体末端点的世界坐标,而不是锚点的位置。按照以下步骤操作即可:
确定目标点的局部坐标
因为你的SCNBox长度为0.02,锚点在中心,所以z轴正方向的末端点在第一个节点的局部坐标系中是:SCNVector3(x: 0, y: 0, z: 0.01);如果是负方向末端则是z: -0.01,根据你的排列方向调整即可。转换为世界坐标
使用SceneKit的convertPosition(_:to:)方法,将局部坐标转换为世界坐标。传入nil表示转换到根节点(世界坐标系):let endPointLocal = SCNVector3(x: 0, y: 0, z: 0.01) let endPointWorld = firstNode.convertPosition(endPointLocal, to: nil)更新第二个节点的位置
直接将第二个节点的position设置为转换后的世界坐标,就能实现跟随效果。
完整代码示例
// 创建第一个节点 let firstBox = SCNBox(width: 0, height: 0, length: 0.02, chamferRadius: 0) let firstNode = SCNNode(geometry: firstBox) firstNode.position = SCNVector3(0, 0, 0) // 初始位置 scene.rootNode.addChildNode(firstNode) // 创建第二个节点 let secondBox = SCNBox(width: 0, height: 0, length: 0.02, chamferRadius: 0) let secondNode = SCNNode(geometry: secondBox) scene.rootNode.addChildNode(secondNode) // 给第一个节点设置旋转(示例:绕y轴转90度) firstNode.rotation = SCNVector4(x: 0, y: 1, z: 0, w: .pi/2) // 计算并更新第二个节点的位置 let endPointLocal = SCNVector3(x: 0, y: 0, z: 0.01) let endPointWorld = firstNode.convertPosition(endPointLocal, to: nil) secondNode.position = endPointWorld
如果需要实时跟随(比如第一个节点在动画中持续旋转),把坐标转换和位置更新的代码放到renderer(_:updateAtTime:)代理方法里即可,这样第二个节点会实时同步位置。
内容的提问来源于stack exchange,提问作者mkz
相关产品推荐
相关产品推荐

