ARオブジェクトの座標を操る方法チートシート


カメラの50cm前に置く

guard let camera = sceneView.pointOfView else {
    return
}
let cameraPos = SCNVector3Make(0, 0, -0.5)
let position = camera.convertPosition(cameraPos, to: nil)
boxNode.position = position

スクリーンのタップした位置の50cm前に置く

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let point = touches.first?.location(in: sceneView) else {
        return
    }
    let infrontOfCamera = SCNVector3(x: 0, y: 0, z: -0.5)

    guard let cameraNode = sceneView.pointOfView else { return }
    let pointInWorld = cameraNode.convertPosition(infrontOfCamera, to: nil)

    var screenPos = sceneView.projectPoint(pointInWorld)

    screenPos.x = Float(point.x)
    screenPos.y = Float(point.y)

    let finalPosition = sceneView.unprojectPoint(screenPos)
    boxNode.position = finalPosition
}

タップして平面、垂直面に置く

水平面 垂直面

configuration

let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = [.horizontal, .vertical]

touchesBegan

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let location = touches.first?.location(in: sceneView),
        let horizontalHit = sceneView.hitTest(
            location,
            types: .existingPlane
            ).first else {
                return
    }
    let column3: simd_float4 = horizontalHit.worldTransform.columns.3
    let position = SCNVector3(column3.x, column3.y, column3.z)
    boxNode.position = position
    sceneView.scene.rootNode.addChildNode(boxNode)
}

任意の方向を向かせる

例:カメラの方向を向かせる

guard let camera = sceneView.pointOfView else {
    return
}
boxNode.look(at: camera.position)

カメラと同じ方向を向かせる

guard let camera = sceneView.pointOfView else {
    return
}
boxNode.eulerAngles = camera.eulerAngles

カメラと同じ高さに置く

guard let camera = sceneView.pointOfView else {
    return
}
let cameraPos = SCNVector3Make(0, 0, -0.5)
var position = camera.convertPosition(cameraPos, to: nil)
position.y = camera.position.y // ここ
boxNode.position = position

カメラから発射する

private func shoot(){
    guard let camera = sceneView.pointOfView else {
       return
    }
    boxNode.position = camera.position

    let targetPosCamera = SCNVector3Make(0, 0, -2)
    let target = camera.convertPosition(targetPosCamera, to: nil)
    let action = SCNAction.move(to: target, duration: 1)
    boxNode.runAction(action)
}

カメラの前に物体をホールド

extension PracticeViewController: ARSCNViewDelegate {
    func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
        // このフラグをボタン等で切り替える
        if holding {
            guard let camera = sceneView.pointOfView else {
                return
            }
            let cameraPos = SCNVector3Make(0, 0, -0.5)
            let position = camera.convertPosition(cameraPos, to: nil)
            boxNode.position = position
        }
    }
}

サンプルコード

サンプルコードはARKit-EmperorのPracticeにあります!