My iOS app uses RealityKit with Physics to move entities. It requires to put objects on a board. This must be done with a totally inelastic impact, i.e. the object must not bounce back when put on the board.
Unfortunately, I was not able to achieve this behavior. I thus wrote a little test app to investigate the situation. This app is shown below.
The app sets up a board and above it a box. Both entities use a physicsBody so that they can participate in the Physics simulation.
The mode of the board is .static, i.e. it does not move. The mode of the box is .dynamic, i.e. it moves immediately after app start down by gravity.
The PhysicsMaterialResource of both entities has its restitution set to 0, i.e. the impact should be totally inelastic.
Both entities have collision shapes, so that the box collides with the board after a short fall.
The essential test parameter is the scaleFactor at the beginning of the code. Depending on its value, I observed different behavior:
- If
scaleFactoris = 0.1, the box collides with the board, and stops as expected. - If
scaleFactoris = 0.02, the box is bounced back hardly, and disappears towards the top. - If
scaleFactoris = 0.01, The box does not collide with the board, and falls through.
I believe this is RealityKit bug, and if somebody can confirm this, I will write a bug report.
The code:
import SwiftUI
@main
struct RestitutionApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
import RealityKit
import SwiftUI
let scaleFactor: Float = 0.1 // correct behavior
//let scaleFactor: Float = 0.02 // impact is not inelastic
//let scaleFactor: Float = 0.01 // box falls through the board
struct ContentView: View {
let scale = scaleFactor * SIMD3<Float>(1, 1, 1)
let boxSize: Float = 0.5/scaleFactor
var body: some View {
RealityView { content in
let board = makeBoard()
board.position = [0, 0, -3]
content.add(board)
let box = makeBox()
box.position = [0, 1, 0]
board.addChild(box)
}
}
func makeBoard() -> ModelEntity {
let mesh = MeshResource.generateBox(width: 2, height: 0.2, depth: 1.0)
var material = UnlitMaterial(); material.color.tint = .red
let boardEntity = ModelEntity(mesh: mesh, materials: [material])
boardEntity.generateCollisionShapes(recursive: false)
let physicsMaterial = PhysicsMaterialResource.generate(friction: 0, restitution: 0)
boardEntity.physicsBody = PhysicsBodyComponent(massProperties: .default,
material: physicsMaterial,
mode: .static) // The board does not move
return boardEntity
}
func makeBox() -> ModelEntity {
let mesh = MeshResource.generateBox(size: boxSize)
var material = UnlitMaterial(); material.color.tint = .green
let boxEntity = ModelEntity(mesh: mesh, materials: [material])
boxEntity.scale = scale
boxEntity.generateCollisionShapes(recursive: false)
let physicsMaterial = PhysicsMaterialResource.generate(friction: 0, restitution: 0)
boxEntity.physicsBody = PhysicsBodyComponent(massProperties: .default,
material: physicsMaterial,
mode: .dynamic)
return boxEntity
}
}