1

好吧,我正在通过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)")
            }

        }

    }

我很迷茫,不知道我是否正确地处理了这件事。我在 ARKit 中引用Detect touch on SCNNode但这不涉及 RealityComposer。

我怎样才能做到这一点?

4

1 回答 1

5

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

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

在此处输入图像描述

然后,这将添加一个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)
    }

}

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

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

  }
}

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

于 2020-02-07T02:16:31.743 回答