【问题标题】:Reality Composer - ar hittest not working?Reality Composer - ar hittest 不工作?
【发布时间】:2020-02-05 19:21:15
【问题描述】:

好的,我正在通过https://developer.apple.com/videos/play/wwdc2019/609/ 提供的 RealityComposer 游戏进行除草,并试图弄清楚如何让实体移动到用户点击的位置。

我可以像这样在我的 .rc 场景中引用我的对象:

struct ARViewContainer: UIViewRepresentable {

    let arView = ARView(frame: .zero)

    func makeUIView(context: Context) -> ARView {

       // arView = ARView(frame: .zero)

        // Load the "Box" scene from the "Experience" Reality File
        let boxAnchor = try! Experience.loadBox()

        //*Notifications
        setupNotifications(anchor: boxAnchor)

        //*Access vars
        if boxAnchor.box1 != nil {
            //print(box1.position.x)
            /// Set local position
            boxAnchor.box1!.position = [1.0, 0.0, 0.5]
            /// Set world position
            //boxAnchor.box1.setPosition([0.5, 0.2, 1.5], relativeTo: nil)
        }

我知道这涉及到某种形式的 arhitest,但是我得到了以下错误:

UIView 最后没有成员?

func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

       //1. Get The Current Touch Location
        guard let currentTouchLocation = touches.first?.location(in: self.arView),

            //2. Get The Tapped Node From An SCNHitTest
            let hitTestResultNode = self.arView.hitTest(currentTouchLocation, with: nil).last?.node else { return } //error here

        //3. Loop Through The ChildNodes
        for node in hitTestResultNode.childNodes{

            //4. If The Node Has A Name Then Print It Out
            if let validName = node.name{
                 print("Node\(validName) Is A Child Node Of \(hitTestResultNode)")
            }

        }

    }

对于我是否完全正确地处理这件事,我很迷茫。我引用了Detect touch on SCNNode in ARKit,但这与 RealityComposer 无关。

我该怎么做?

【问题讨论】:

    标签: swift arkit reality-composer


    【解决方案1】:

    Entity 通过触摸移动的最简单方法是使用 Apple 提供的内置手势;您可以在此处阅读更多信息:Apple Documentation

    要启用您选择的手势(在本例中为翻译),请首先确保在 RealityComposer 中将您希望与之交互的每个 Entity 上的 partcipates 值设置为 true

    然后将Has Collision 组件添加到Entity,这很简单:

    使实体能够与也具有碰撞组件的其他实体发生碰撞的组件。

    使用它,您可以安装内置手势来为您完成繁重的工作。

    假设我们在Xcode 中有默认的RealityKit 示例设置,并且我们为盒子选择了参与,它很简单,让用户可以使用触摸位置来平移它:

    class ViewController: UIViewController {
    
        @IBOutlet var arView: ARView!
    
        override func viewDidLoad() {
    
          super.viewDidLoad()
    
            //1. Load The Box Anchor
            let boxAnchor = try! Experience.loadBox()
    
            //2. Check The SteelBox Has A Collision Component & Add The Desired Gesture
            if let hasCollision = boxAnchor.steelBox as? HasCollision {
              arView.installGestures(.translation, for: hasCollision)
           }
    
           //Add The Box To The Scene Hierachy
           arView.scene.anchors.append(boxAnchor)
        }
    
    }
    

    或者,如果您想做一些繁重的工作(谁不想!),那么您可以通过创建一个全局变量来执行类似的操作,该变量将引用您选择的实体(在本例中称为钢盒) :

    //Variable To Store Our Currently Selected Entity
    var currentEntity: Entity?
    

    然后使用touchesBegantouchesMoved 你可以这样:

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    
      /* Get The Current Touch Location In The ARView
       Perform A HitTest For The Nearest Entity
       Checks That The Tapped Entity Is The Steel Box
       Set It As The Current Entity
       */
      guard let touchLocation = touches.first?.location(in: arView),
        let tappedEntity = arView.hitTest(touchLocation, query: .nearest, mask: .default).first?.entity,
        tappedEntity.name == "Steel Box" else {
          return
      }
    
      currentEntity = tappedEntity
    
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    
      /* Get The Current Touch Location In The ARView
       Perform A HitTest For An Existing Plane
       Move The Current Entity To The New Transfortm
       Set It As The Current Entity
       */
      guard let touchLocation = touches.first?.location(in: arView),
        let currentEntity = currentEntity else {
          return
      }
    
      if let transform = arView.hitTest(touchLocation, types: .existingPlaneUsingExtent).first?.worldTransform {
        currentEntity.move(to: transform, relativeTo: nil, duration: 0.1)
    
      }
    }
    

    希望它有助于指出正确的方向。

    【讨论】:

    • 你拯救了我的一天!谢谢你:)
    • 快乐 :) @Picode
    猜你喜欢
    • 2022-01-22
    • 2021-07-31
    • 2019-10-25
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 2020-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多