Search code examples
swiftarkitrealitykitreality-composer

Custom collision shape appears in wrong position


I load an Entity from Reality Composer and I add a custom CollisionShape.

These are the steps I follow:

// I get the `.reality` url and I load the model
let rocketSceneUrl = Bundle.main.url(forResource: "Experience", 
                                   withExtension: "reality")!
                                        .appending(path: "RocketScene", 
                                          directoryHint: .notDirectory)

let rocketScene = try Entity.load(contentsOf: rocketSceneUrl)

// I get the visual bounds of the `boxScene`
let visualBounds = rocketScene.visualBounds(
                                  recursive: true, 
                                 relativeTo: self, 
                            excludeInactive: false)

// I generate the custom shape resource. 
// I use the y for the height, and half the boundingRadius
let shapeResource = ShapeResource.generateCapsule(
                                    height: bounds.extents.y, 
                                    radius: bounds.boundingRadius / 2)

// I create the custom `CollisionComponent`
let collision = CollisionComponent(
                            shapes: [shapeResource], 
                              mode: .trigger, 
                            filter: .sensor)

// I set the component on the `Entity`
rocketScene.components.set(collision)

// Then I add the `Entity` in the scene.

And this is what I get:

enter image description here

The Entity with its collision shape appears below the actual content, or conversely the actual content appears above the Entity and its custom collision shape.

I guess that when RealityKit adds the Entity on a surface, it compensates by moving the contents in such a way so that it appears to be sitting on the plane, but I may be mistaken.

My question is how do I make the custom collision shape be at the same location where the contents of the Entity are?


Solution

  • Repositioning a ShapeResource's mesh

    Your Custom Collision Shape's mesh is properly placed in the RealityKit's scene because its center perfectly matches the model's pivot point position. To reposition your shapeResource, use the offsetBy(translation:) modifier to move it along +Y direction.

    @MainActor func offsetBy(translation: SIMD3<Float>) -> ShapeResource
    

    Here's a code:

    import UIKit
    import RealityKit
    
    class ViewController: UIViewController {
    
        @IBOutlet var arView: ARView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
     
            arView.debugOptions = .showPhysics
            
            let entity = try! Entity.load(named: "Rocket.reality")
            
            let bounds = entity.visualBounds(recursive: true,
                                            relativeTo: nil,
                                       excludeInactive: false)
            
            var shapes: ShapeResource = ShapeResource.generateCapsule(
                                               height: bounds.extents.y,
                                               radius: bounds.boundingRadius / 2)
                                        .offsetBy(translation: [0, 0.5, 0])
                                           
            let collision = CollisionComponent(shapes: [shapes],
                                                 mode: .trigger,
                                               filter: .sensor)    
            entity.components.set(collision)
            
            let anchor = AnchorEntity()
            anchor.addChild(entity)
            arView.scene.anchors.append(anchor)
        }
    }
    

    Also, this post may be helpful for you.