Search code examples
swiftarkitrealitykitreality-composer

Collider does not works properly in RealityKit


I have a .rcproject file with a goal (football gate) and a ball, the ball has physics of Dynamic and Rubber material, and the goal is Fixed with Lead material. When I load the scene from the .rcproject file, I set the goal collider to be the exact mesh of the tubes that make the goal's frame and the net, using generateConvex of the model.mesh.

But, it seems like the ball is touching the goal, and it collides with some invisible wall that is at the "entrance" of the goal, kinda like it's just a 2d wall, instead of the ball actually going inside the goal like it would in real life. This is my code:

Experience.loadSceneAsync { result in
    switch result {
        case let .success(scene):
            guard let tubeOneGeometry = scene.findEntity(named: "Tube_Red_0")?.children[0] as? ModelEntity,
                  let tubeTwoGeometry = scene.findEntity(named: "Tube_White_0")?.children[0] as? ModelEntity,
                  let netGeometry = scene.findEntity(named: "Net_Net_0")?.children[0] as? ModelEntity,
                  let tubeOneMesh = tubeOneGeometry.model?.mesh,
                  let tubeTwoMesh = tubeTwoGeometry.model?.mesh,
                  let netMesh = netGeometry.model?.mesh,
                  let goal = scene.goal 
            else { return }

            let tubeOneShape = ShapeResource.generateConvex(from: tubeOneMesh)
            let tubeTwoShape = ShapeResource.generateConvex(from: tubeTwoMesh)
            let netShape = ShapeResource.generateConvex(from: netMesh)
            goal.components[CollisionComponent.self] = CollisionComponent(
                            shapes: [tubeOneShape, tubeTwoShape, netShape])    
            arView.debugOptions.insert(.showPhysics)

            let anchor = AnchorEntity(plane: .horizontal)
            anchor.addChild(scene)
            arView.scene.addAnchor(anchor)

        case let .failure(error):
            print("Failed to load scene: \(error)")
    }
}

Solution

  • Low-rez Collision Shape

    You forgot to turn the default collision shape for the football gate OFF. Also, the generateConvex(from:) method built an irregularly shaped collision shape. Use the following code to generate robust collision shape programmatically (however, a good practice is to create a low-resolution collision shape in 3D authoring apps like Autodesk Maya):

    import UIKit
    import RealityKit
    
    class ViewController: UIViewController {
        @IBOutlet var arView: ARView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
                            
            Experience.loadSoccerAsync { result in
                switch result {
                    case let .success(scene):
                        guard let goal = scene.goal else { return }
                        goal.components[CollisionComponent.self] = .none
    
                        let right = ShapeResource.generateCapsule(height: 3, radius: 0.13)
                                        .offsetBy(translation: [0,1.5,1.83])
                        let left = ShapeResource.generateCapsule(height: 3, radius: 0.13)
                                        .offsetBy(translation: [0,1.5,-1.83])
                        let upper = ShapeResource.generateCapsule(height: 4.1, radius: 0.12)
                                        .offsetBy(rotation: simd_quatf(angle: .pi/2, axis: [1,0,0]),
                                               translation: [0,2.8,0])
                        let net = ShapeResource.generateBox(width: 0.01, height: 3.3, depth: 3.9)
                                        .offsetBy(rotation: simd_quatf(angle: -.pi/4, axis: [0,0,1]),
                                               translation: [-1.3,1.4,0])
                        goal.components[CollisionComponent.self] =
                                        CollisionComponent(shapes: [right, left, upper, net])
    
                        self.arView.debugOptions = [.showPhysics]    
                        goal.scale /= 2
                    
                        let anchor = AnchorEntity()
                        anchor.addChild(scene)
                        self.arView.scene.addAnchor(anchor)
    
                    case let .failure(error):
                        print("Failed to load scene: \(error)")
                }
            }
        }
    }
    

    enter image description here