Реальность Composer - Хиттест не работает? - PullRequest
0 голосов
/ 05 февраля 2020

Хорошо, я прохожу через предоставленную игру Reality Composer на https://developer.apple.com/videos/play/wwdc2019/609/ и пытаюсь выяснить, как заставить существо двигаться, куда пользователь нажимает.

Я могу ссылаться на мои объекты в моей сцене .r c следующим образом:

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

Я знаю, что это связано с какой-либо формой архива, однако при следующем я получаю ошибку:

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

        }

    }

Я довольно растерян, чтобы понять, правильно ли я поступаю по этому поводу. Я ссылаюсь на Обнаружение касания на SCNNode в ARKit , но это не касается Реальности Composer.

Как я могу это сделать?

1 Ответ

0 голосов
/ 07 февраля 2020

Самый простой способ заставить Entity двигаться через прикосновение - это использовать встроенные жесты, предоставляемые Apple; о которой вы можете прочитать здесь: Документация Apple

Чтобы включить ваш жест выбора (в данном случае перевод), сначала убедитесь, что в RealityComposer установлено значение partcipates на true на каждом Entity, с которым вы будете sh взаимодействовать.

enter image description here

Затем добавляется 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?

Затем, используя touchesBegan и touchesMoved, вы можете что-то вроде этого:

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)

  }
}

Надеюсь, это поможет направить в правильном направлении.

...