Implementing a bouncing surface

I am trying to simulate a pinball game and I want to use PhysicsBody & PhysicsMotion to achieve that. I tuned the parameters around in PhysicsBodyComponent, but the result is not quite ideal for now.

Imagine a fully inflated basketball bouncing high off the ground (ground vs basketball). I assign PhysicsBodyComponent and CollisionComponent to both basketball and the ground.

For basket ball, I set it as:

  1. dynamic mode
  2. mass 1, inertia .one
  3. Material.Restitution 1
  4. Angular Damping and Linear Damping to 0
  5. AddForce to make the basketball move to hit the ground

For ground, I set it as:

  1. static mode
  2. mass 1, inertia .zero
  3. Material.Restitution 1
  4. Angular Damping and Linear Damping to 0

However, when the basket ball hit the ground, it isn't that bouncy, the basketball behaves like hitting to a cotton and the linear speed just dumps fast. Wonder how I could achieve the bouncing effect like real basketball vs ground.

Answered by Vision Pro Engineer in 795202022

I'm surprised to hear you don't get more bounce. Without seeing all the code it's hard to tell why. Here's a rough example of a simulation for a basketball on an indoor court. I did some research to find the correct input parameters to supply to PhysicsBodyComponent. A higher restitution will result in more bounce. Tap on the ball to see it bounce. Hopefully that points you in the right direction. If it doesn't, please reply with a focused code sample so I can better help.

struct ImmersiveView: View {
    
    var body: some View {
        RealityView { content in
            let root = Entity()
            
            let floor = ModelEntity(mesh: .generatePlane(width: 15, depth: 28), materials: [SimpleMaterial(color: .brown, isMetallic: false)])
            
            let ballRadius:Float = 0.121
            let ball = ModelEntity(mesh: .generateSphere(radius: ballRadius), materials: [SimpleMaterial(color: .orange, isMetallic: false)])
            
            // Make sure to set the appropriate collision shape
            ball.components.set(CollisionComponent(shapes: [.generateSphere(radius: ballRadius)]))
            ball.components.set(InputTargetComponent())
            ball.position = [0, 0, -4.0]
            
            floor.generateCollisionShapes(recursive: false)
            ball.generateCollisionShapes(recursive: false)
            
            guard let floorShapes = floor.collision?.shapes, let ballShapes = ball.collision?.shapes else {return}
            
            let floorPhysicsBodyComponent = PhysicsBodyComponent(
                shapes: floorShapes,
                density: 700,
                material: .generate(staticFriction: 0.7, dynamicFriction: 0.6, restitution: 0.88),
                mode: .static
            )
                        
            floor.components.set(floorPhysicsBodyComponent)
            
            var basketballPhysicsBodyComponent = PhysicsBodyComponent(
                shapes: ballShapes,
                mass: 0.624,
                material: .generate(staticFriction: 0.8, dynamicFriction: 0.6, restitution: 0.6),
                mode: .dynamic)
            
            basketballPhysicsBodyComponent.angularDamping = 0.05
            basketballPhysicsBodyComponent.linearDamping = 0.1
            ball.components.set(basketballPhysicsBodyComponent)
            
            root.addChild(floor)
            root.addChild(ball)
            
            content.add(root)
        }
        .gesture(TapGesture().targetedToAnyEntity().onEnded { event in
            guard let entity = event.entity as? ModelEntity else {return}
            
            let force:Float = 0.8
            entity.applyLinearImpulse([0, 5, -1] * force, relativeTo: nil)
        })
    }
}

I'm surprised to hear you don't get more bounce. Without seeing all the code it's hard to tell why. Here's a rough example of a simulation for a basketball on an indoor court. I did some research to find the correct input parameters to supply to PhysicsBodyComponent. A higher restitution will result in more bounce. Tap on the ball to see it bounce. Hopefully that points you in the right direction. If it doesn't, please reply with a focused code sample so I can better help.

struct ImmersiveView: View {
    
    var body: some View {
        RealityView { content in
            let root = Entity()
            
            let floor = ModelEntity(mesh: .generatePlane(width: 15, depth: 28), materials: [SimpleMaterial(color: .brown, isMetallic: false)])
            
            let ballRadius:Float = 0.121
            let ball = ModelEntity(mesh: .generateSphere(radius: ballRadius), materials: [SimpleMaterial(color: .orange, isMetallic: false)])
            
            // Make sure to set the appropriate collision shape
            ball.components.set(CollisionComponent(shapes: [.generateSphere(radius: ballRadius)]))
            ball.components.set(InputTargetComponent())
            ball.position = [0, 0, -4.0]
            
            floor.generateCollisionShapes(recursive: false)
            ball.generateCollisionShapes(recursive: false)
            
            guard let floorShapes = floor.collision?.shapes, let ballShapes = ball.collision?.shapes else {return}
            
            let floorPhysicsBodyComponent = PhysicsBodyComponent(
                shapes: floorShapes,
                density: 700,
                material: .generate(staticFriction: 0.7, dynamicFriction: 0.6, restitution: 0.88),
                mode: .static
            )
                        
            floor.components.set(floorPhysicsBodyComponent)
            
            var basketballPhysicsBodyComponent = PhysicsBodyComponent(
                shapes: ballShapes,
                mass: 0.624,
                material: .generate(staticFriction: 0.8, dynamicFriction: 0.6, restitution: 0.6),
                mode: .dynamic)
            
            basketballPhysicsBodyComponent.angularDamping = 0.05
            basketballPhysicsBodyComponent.linearDamping = 0.1
            ball.components.set(basketballPhysicsBodyComponent)
            
            root.addChild(floor)
            root.addChild(ball)
            
            content.add(root)
        }
        .gesture(TapGesture().targetedToAnyEntity().onEnded { event in
            guard let entity = event.entity as? ModelEntity else {return}
            
            let force:Float = 0.8
            entity.applyLinearImpulse([0, 5, -1] * force, relativeTo: nil)
        })
    }
}

@Vision Pro Engineer Thanks for your reply and your help! I just copy and paste all of the parameters in your code snippet. But this still not works. I didn't paste the code because most of the component's parameters are set in Reality Composer Pro. You can see that in my attachments.

I am thinking it's about ModelEntity. In my case, "Qiu" is a ball with sphere collision box, but I checked that in my code, Qiu cannot be cast into a ModelEntity. I am thinking probably the Entity itself doesn't have a mesh attached to it, because Qiu is imported from a DCC, it has a child Entity containing a meshResource (but no collision sphere attached to this Entity).

But as the document said, as long as an Entity has PhysicsBodyComponent and a CollisionComponent, it should have the ability to participate physics simulation. Or there must be some misalignment between RealityComposerPro and RealityKit

I’m not an expert in Realty Composer Pro so I only have standard troubleshooting advice to offer. Let’s narrow down the cause of the issue. Replace “Qiu” with a primitive sphere; that will help us determine if the issue is specific to your model. Let me know if that doesn’t reveal something that helps you resolve the issue and I’ll see if I can get someone from the Reality Composer Pro team to help next week.

I just tried to reproduce this with a primitive box and sphere and noticed Qui's Physics Body is not "Affected by Gravity". It needs to be; after I checked "Affected by Gravity" the sphere bounces as expected. Please check the checkbox and let me know if that resolves the issue.

Implementing a bouncing surface
 
 
Q