You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

已知Y高度,如何在SceneKit中通过点击SCNView获取X、Z坐标?

在SCNView中点击空白处获取指定Y高度的世界坐标(X、Z)

核心思路是通过屏幕点击坐标生成3D空间射线,再计算这条射线与指定Y高度平面的交点,从而得到对应的X、Z坐标。具体实现步骤如下:

1. 转换屏幕坐标为3D射线

利用SCNView的unprojectPoint(_:)方法,将屏幕点击点分别转换为近裁剪面(Z=0)和远裁剪面(Z=1)上的3D点,这两个点共同定义了一条穿过点击位置的空间射线。

2. 计算射线与指定Y平面的交点

射线的参数方程可以表示为:nearPoint + t * direction,其中direction是远平面点减去近平面点的方向向量。我们需要找到参数t使得射线的Y分量等于目标高度targetY,代入后即可解出对应的X、Z值。

完整代码实现(Swift)

func getTargetWorldPosition(at touchPoint: CGPoint, in scnView: SCNView, targetY: Float) -> SCNVector3? {
    // 将屏幕坐标转为近、远平面的3D点
    let nearPoint = scnView.unprojectPoint(SCNVector3(touchPoint.x, touchPoint.y, 0))
    let farPoint = scnView.unprojectPoint(SCNVector3(touchPoint.x, touchPoint.y, 1))
    
    // 计算射线方向向量
    let direction = SCNVector3(
        x: farPoint.x - nearPoint.x,
        y: farPoint.y - nearPoint.y,
        z: farPoint.z - nearPoint.z
    )
    
    // 避免射线与目标平面平行(Y方向无分量)
    guard abs(direction.y) > 0.0001 else {
        return nil
    }
    
    // 求解参数t,让射线Y分量等于目标高度
    let t = (targetY - nearPoint.y) / direction.y
    
    // 计算最终的X、Z坐标
    let targetX = nearPoint.x + t * direction.x
    let targetZ = nearPoint.z + t * direction.z
    
    return SCNVector3(targetX, targetY, targetZ)
}

使用示例

在点击手势回调中,先通过常规hitTest检测是否有相交物体,无相交时调用上述方法获取坐标并放置物体:

@objc func handleScreenTap(_ gesture: UITapGestureRecognizer) {
    guard let scnView = gesture.view as? SCNView else { return }
    let touchPoint = gesture.location(in: scnView)
    
    // 先检测是否点击到场景中的物体
    let hitResults = scnView.hitTest(touchPoint, options: nil)
    if hitResults.isEmpty {
        // 假设要放置在Y=0的高度平面上
        if let targetPos = getTargetWorldPosition(at: touchPoint, in: scnView, targetY: 0) {
            // 创建示例物体并放置
            let cube = SCNBox(width: 0.2, height: 0.2, length: 0.2, chamferRadius: 0)
            let cubeNode = SCNNode(geometry: cube)
            cubeNode.position = targetPos
            scnView.scene?.rootNode.addChildNode(cubeNode)
        }
    }
}

注意事项

  • 若射线几乎平行于目标Y平面(direction.y趋近于0),会返回nil以避免计算误差;
  • 确保targetY的取值符合你的场景坐标系(SceneKit默认Y轴向上);
  • Objective-C实现逻辑完全一致,仅需调整语法细节。

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 09:23:08