【问题标题】:Realitykit / ArKit make a collision only between 2 objectsRealitykit / ArKit 仅在 2 个对象之间发生碰撞
【发布时间】:2023-01-31 00:09:02
【问题描述】:

我有一个球和一个圆柱体。当我轻敲球时,它会向前移动。当球击中圆柱体时,它们发生碰撞,圆柱体移动并改变颜色。那工作正常。

我有两个问题: 当我启动应用程序时,圆柱体不断碰撞并立即改变颜色,所以即使球不在它附近。它看起来像是与其他东西相撞。

第二件事是,场景中会有更多的圆柱体,我怎样才能只在两个物体之间产生碰撞事件。假设场景中有 2 个圆柱体,如何设置过滤器或组。

import SwiftUI
import RealityKit
import ARKit
import FocusEntity
import Combine

struct ContentView : View {
    
    
    var body: some View {

            ARViewContainer()
            
    }
}

struct ARViewContainer: UIViewRepresentable {


    func makeUIView(context: Context) -> ARView {
        
        let view = ARView()

        let session = view.session
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = .horizontal
        session.run(config)

        let coachingOverlay = ARCoachingOverlayView()
        coachingOverlay.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        coachingOverlay.session = session
        coachingOverlay.goal = .horizontalPlane
        view.addSubview(coachingOverlay)

        context.coordinator.view = view
        session.delegate = context.coordinator
        
        view.addGestureRecognizer(UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap)))
        
        return view
        
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {}
    
    
    func makeCoordinator() -> Coordinator {
        Coordinator()
    }



//coordinator class
class Coordinator: NSObject,ARSessionDelegate {
    
    weak var view: ARView?
    var focusEntity: FocusEntity?
    
    @Published var sceneIsPlaced:Bool = false //is de scene reeds geplaats na openen app
    @Published var subscriptions: [AnyCancellable] = []


    func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
        guard let view = self.view else { return }
        self.focusEntity = FocusEntity(on: view, style: .classic(color: .yellow))
    }
    
    
    //na tap op het scherm, wat te doen -> creeer locatie en plaats het object
    @objc func handleTap(recognizer: UITapGestureRecognizer) {
        
        
            guard let view = self.view, let focusEntity = self.focusEntity else { return }
            
            //tap location van de tap gesture
            let tapLocation =  recognizer.location(in: self.view)
     
            //Create Anchor
            let anchor = AnchorEntity()
        

            let importModel = try! Entity.load(named: "cilinder") //alle objects!
            importModel.position = focusEntity.position
            importModel.scale = SIMD3(repeating: 0.5)

        
            //The cylinder
            let kolomMiddleModel = importModel.findEntity(named: "cilinder")!.children[0] as! (ModelEntity & HasPhysicsBody & HasCollision)
            let materialKolomMiddle = SimpleMaterial(color: .yellow, isMetallic: true)
            kolomMiddleModel.model?.materials = [materialKolomMiddle]
            kolomMiddleModel.generateCollisionShapes(recursive: false)
            let physics = PhysicsBodyComponent(massProperties: .default, material: .default, mode: .dynamic)
            kolomMiddleModel.components.set(physics)

            //MAKE A BALL
            let materialsBall = SimpleMaterial(color: .red, isMetallic: true)
            let ballModel = ModelEntity(mesh: .generateSphere(radius: 0.1),
                                           materials: [materialsBall])
                                                               as (Entity & HasPhysicsBody & HasCollision)
                 
            ballModel.position = [-0.1, -1.0,-0.1]
            ballModel.generateCollisionShapes(recursive: true)
            ballModel.name = "ballModel"

            //LIGHTS --> let op voor de shadow moet de plane van occlusion material met dynamical lightning op tue
            let directionalLight = DirectionalLight()
            directionalLight.light.color = .white
            directionalLight.light.intensity = 4000
            directionalLight.light.isRealWorldProxy = true
            directionalLight.shadow?.maximumDistance = 1.5
            directionalLight.shadow?.depthBias = 7.0
            directionalLight.orientation = simd_quatf(angle: .pi/1.5, axis: [0,1,0])
            
            //maak een anchor voor het licht
            let lightAnchor = AnchorEntity(world: [0, 0, 2.5])
            lightAnchor.addChild(directionalLight)
            
            
            //COLLISION EVENTS
            DispatchQueue.main.async {

                //collision of kolomModel
                view.scene.subscribe(to: CollisionEvents.Began.self,
                                     on: kolomMiddleModel) { _ in
                    print("Collision kolomModel detected!")
                    let material = SimpleMaterial(color: .red, isMetallic: true)
                    kolomMiddleModel.model?.materials = [material]

                }.store(in: &self.subscriptions)
            }
            
            
//            view.installGestures(for: ballModel)
//
        
            //PLACE SCENE IF NOT PLACED ALREADY
            if !sceneIsPlaced {
                //ADD MODELS TO ANCHOR
             
                anchor.addChild(importModel)
                anchor.addChild(ballModel)
                anchor.addChild(lightAnchor)
                
                view.scene.addAnchor(anchor)
                sceneIsPlaced = true
                
            //If the scene is already placed get the taplocation
            }else{
                if let locationEntity = view.entity(at: tapLocation) {
                    let entityTapped = locationEntity as! ModelEntity
               
                    //MAKE THE BALL GO FORWARD
                    print("entity tapped \(entityTapped)")
                    entityTapped.physicsBody = .init()
                    entityTapped.physicsBody?.mode = .kinematic
                    entityTapped.physicsMotion = PhysicsMotionComponent(linearVelocity: [0, 0, -0.5],
                                                                       angularVelocity: [1, 3, 5])
 
                }
            }
        
    }
        
    }
}

【问题讨论】:

    标签: swiftui arkit realitykit


    【解决方案1】:

    这是 RealityKit 中两个只能相互碰撞的对象的示例:

    let sphere = ModelEntity(mesh: .generateSphere(radius: 0.1), materials: [SimpleMaterial()])
    sphere.collision = CollisionComponent(shapes: [ShapeResource.generateSphere(radius: 0.1)])
    sphere.collision?.filter = CollisionFilter(group: 1 << 2, categories: .default, mask: .default)
    
    let cube = ModelEntity(mesh: .generateBox(size: [0.1, 0.1, 0.1]), materials: [SimpleMaterial()])
    cube.collision = CollisionComponent(shapes: [ShapeResource.generateBox(size: [0.1, 0.1, 0.1])])
    cube.collision?.filter = CollisionFilter(group: 1 << 1, categories: .default, mask: .default)
    
    sphere.collision?.filter.collisionGroup = 1 << 1
    cube.collision?.filter.collisionGroup = 1 << 2
    
    arView.scene.addAnchor(sphere)
    arView.scene.addAnchor(cube)
    

    此代码创建两个对象:一个球体和一个立方体。每个对象都被赋予一个 CollisionComponent 以及相应的 ShapeResource 和 CollisionFilter。每个对象的 CollisionFilter 指定只有不同 collisionGroup 中的对象才能与其发生碰撞。结果,球体和立方体只能相互碰撞,而不能与场景中的其他物体发生碰撞。

    在此处查看有关 CollisionGroups 的更多信息: https://developer.apple.com/documentation/realitykit/collisionfilter

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多