Reality Composer - настраиваемое столкновение между объектами разных сцен

Я новичок в RealityKit и ARKit. У меня есть две сцены в Reality Composer: одна с привязкой к книжному изображению, а другая с привязкой к горизонтальной плоскости. Первая сцена с привязкой к изображению имеет куб, прикрепленный к вершине, а вторая сцена, построенная на горизонтальной плоскости, имеет два кольца. Все объекты имеют фиксированное столкновение. Я бы хотел запустить анимацию, когда кольца и куб соприкасаются. Мне не удалось найти способ сделать это в Reality Composer, поэтому я сделал две попытки в коде, но безрезультатно. (Я печатаю "столкновение началось", просто чтобы проверить код столкновения без анимации) К сожалению, это не сработало. Был бы признателен за помощь в этом.

Попытка №1:

func makeUIView(context: Context) -> ARView {

    let arView = ARView(frame: .zero)

    let componentBreakdownAnchor = try! CC.loadComponentBreakdown()

    arView.scene.anchors.append(componentBreakdownAnchor)

    let bookAnchor = try! CC.loadBook()
    arView.scene.anchors.append(bookAnchor)   

    let ringsAnchor = try! CC.loadRings()
    arView.scene.anchors.append(ringsAnchor)

    // Add the componentBreakdown anchor to the scene
    arView.scene.anchors.append(componentBreakdownAnchor)

    let bookAnchor = try! CC.loadBook()
    arView.scene.anchors.append(bookAnchor)    

    let ringsAnchor = try! CC.loadRings()
    arView.scene.anchors.append(ringsAnchor)

    let _ = ringsAnchor.scene?.subscribe(
    to: CollisionEvents.Began.self,
    on: bookAnchor
    ) { event in
      print("collision started")
    }

    return arView
}

Попытка №2

func makeUIView(context: Context) -> ARView {

    let arView = ARView(frame: .zero)

    let componentBreakdownAnchor = try! CC.loadComponentBreakdown()

    arView.scene.anchors.append(componentBreakdownAnchor)

    let bookAnchor = try! CC.loadBook()
    arView.scene.anchors.append(bookAnchor)  

    let ringsAnchor = try! CC.loadRings()
    arView.scene.anchors.append(ringsAnchor)

    // Add the componentBreakdown anchor to the scene
    arView.scene.anchors.append(componentBreakdownAnchor)

    let bookAnchor = try! CC.loadBook()
    arView.scene.anchors.append(bookAnchor)   

    let ringsAnchor = try! CC.loadRings()
    arView.scene.anchors.append(ringsAnchor)

    arView.scene.subscribe(
      to: CollisionEvents.Began.self,
      on: bookAnchor

    ) { event in
      print("collision started")
    }

    return arView
}

1 ответ

Решение

RealityKit сцена

Если вы хотите использовать коллизии моделей, сделанные в сцене RealityKit с нуля, сначала вам нужно реализовать HasCollision протокол.

Посмотрим, что об этом говорится в документации разработчика:

HasCollision Протокол - это интерфейс, используемый для распределения лучей и обнаружения столкновений.

Вот как должна выглядеть ваша реализация, если вы создаете модели в RealityKit:

import Cocoa
import RealityKit

class CustomCollision: Entity, HasModel, HasCollision {

    let color: NSColor = .gray
    let collider: ShapeResource = .generateSphere(radius: 0.5)
    let sphere: MeshResource = .generateSphere(radius: 0.5)

    required init() {
        super.init()

        let material = SimpleMaterial(color: color,
                                 isMetallic: true)

        self.components[ModelComponent] = ModelComponent(mesh: sphere,
                                                    materials: [material])

        self.components[CollisionComponent] = CollisionComponent(shapes: [collider],
                                                                   mode: .trigger,
                                                                 filter: .default)
    }
}

Реальность Композитор сцена

А вот как должен выглядеть ваш код, если вы используете модели из Reality Composer:

import UIKit
import RealityKit
import Combine

class ViewController: UIViewController {

    @IBOutlet var arView: ARView!
    var subscriptions: [Cancellable] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        let groundSphere = try! Experience.loadStaticSphere()
        let upperSphere = try! Experience.loadDynamicSphere()

        let gsEntity = groundSphere.children[0].children[0].children[0]
        let usEntity = upperSphere.children[0].children[0].children[0]

        // CollisionComponent exists in case you turn on 
        // "Participates" property in Reality Composer app
        print(gsEntity)   

        let gsComp: CollisionComponent = gsEntity.components[CollisionComponent]!.self
        let usComp: CollisionComponent = usEntity.components[CollisionComponent]!.self

        gsComp.shapes = [.generateBox(size: [0.05, 0.07, 0.05])]
        usComp.shapes = [.generateBox(size: [0.05, 0.05, 0.05])]

        gsEntity.components.set(gsComp)
        usEntity.components.set(usComp)

        let subscription = self.arView.scene.subscribe(to: CollisionEvents.Began.self,
                                                       on: gsEntity) { event in
            print("Balls' collision occured!")
        }
        self.subscriptions.append(subscription)

        arView.scene.anchors.append(upperSphere)
        arView.scene.anchors.append(groundSphere)
    }
}

Другие вопросы по тегам