Reality Composer - ar hittest 不起作用?

sky*_*guy 1 swift arkit reality-composer

好吧,我通过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)
        }
Run Code Online (Sandbox Code Playgroud)

我知道这涉及某种形式的 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)")
            }

        }

    }
Run Code Online (Sandbox Code Playgroud)

我很不知道我是否正确地处理了这件事。我引用了ARKit 中 SCNNode 上的检测触摸,但这不涉及 RealityComposer。

我怎样才能做到这一点?

Bla*_*orz 5

通过触摸进行移动的最简单方法Entity是使用 Apple 提供的内置手势;您可以在这里阅读更多相关信息:Apple 文档

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

在此输入图像描述

然后添加一个Has Collision组件,它Entity很简单:

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

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

假设我们在 中进行了默认RealityKit示例设置Xcode,并且我们为该框选择了参与,那么用户可以使用触摸位置平移它,就像这样简单:

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)
    }

}
Run Code Online (Sandbox Code Playgroud)

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

//Variable To Store Our Currently Selected Entity
var currentEntity: Entity?
Run Code Online (Sandbox Code Playgroud)

然后使用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)

  }
}
Run Code Online (Sandbox Code Playgroud)

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