Reality Composer - 不同场景实体之间的自定义碰撞

Reality Composer - Custom Collision Between Entities of Different Scenes

我对 RealityKit 和 ARKit 还很陌生。我在 Reality Composer 中有两个场景,一个带有书本图像锚点,一个带有水平面锚点。带有图像锚点的第一个场景有一个立方体连接到它的顶部,第二个场景建立在水平面上有两个环。所有对象都有固定的碰撞。我想要 运行 圆环和立方体接触时的动画。我找不到在 Reality Composer 中执行此操作的方法,因此我在代码中进行了两次尝试,但无济于事。 (我正在打印 "collision started" 只是为了测试没有动画的碰撞代码)不幸的是,它没有用。非常感谢对此的帮助。

尝试 #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
}

RealityKit 场景

如果你想从头开始使用RealityKit场景中的模型碰撞,首先你需要实现一个HasCollision协议。

让我们看看开发者文档是怎么说的:

HasCollision protocol is an interface used for ray casting and collision detection.

如果您在 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 场景

如果您使用 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)
    }
}