The setup:
My Vision Pro app loads uszd models created by a 3rd party app. These models have to be scaled to the right dimension for RealityKit.
I want to use physics for realistic movement of these entities, but this does not work as expected.
I thus wrote a demo test app based on Apple's immersive space app template (code below).
This app has two entities, a board and above a box that is a child of the board.
Both have a collision component and a physics body.
The board, and thus also its child the box, are scaled.
The problem:
If the scale factor is greater or equal 0.91, the box falls under gravity towards the board where it is stopped after some movements. This looks realistic.
However, if the scale factor is below 0.91, even 0.9, the movement of the box is immediately stopped on the board without any physics simulation.
Unfortunately, I am not able to upload screen recordings, but if the demo app is executed, one sees the effect immediately.
The question:
I cannot imagine that this behavior is correct. Can somebody confirm that this is a bug? If so I will write a bug report.
My demo app uses Xcode Version 16.0 (16A242d), simulator Version 16.0 (1038) and visionOS 2.0.
The code:
import SwiftUI
import RealityKit
import RealityKitContent
struct ImmersiveView: View {
@Environment(AppModel.self) var appModel
var body: some View {
RealityView { content in
let boardEntity = makeBoard()
content.add(boardEntity)
let boxEntity = makeBox()
boardEntity.addChild(boxEntity)
moveBox(boxEntity, parentEntity: boardEntity)
}
}
func makeBoard() -> ModelEntity {
let mesh = MeshResource.generateBox(width: 1.0, height: 0.05, depth: 1.0)
var material = UnlitMaterial(); material.color.tint = .red
let boardEntity = ModelEntity(mesh: mesh, materials: [material])
let scale: Float = 0.91 // Physics does not run if scale < 0.91
boardEntity.scale = [scale, scale, scale]
boardEntity.transform.translation = [0, 0, -3]
boardEntity.generateCollisionShapes(recursive: false)
boardEntity.physicsBody = PhysicsBodyComponent(massProperties: .default,
material: PhysicsMaterialResource.generate(friction: .infinity, restitution: 0.8),
mode: .static)
return boardEntity
}
func makeBox() -> ModelEntity {
let mesh = MeshResource.generateBox(size: 0.2)
var material = UnlitMaterial(); material.color.tint = .green
let boxEntity = ModelEntity(mesh: mesh, materials: [material])
boxEntity.generateCollisionShapes(recursive: false)
boxEntity.physicsBody = PhysicsBodyComponent(massProperties: .default,
material: PhysicsMaterialResource.generate(friction: .infinity, restitution: 0.8),
mode: .dynamic)
return boxEntity
}
func moveBox(_ boxEntity:Entity, parentEntity: Entity) {
// Set position and orientation of the box
let translation = SIMD3<Float>(0, 0.5, 0)
// Turn the box by 45 degrees around the y axis
let rotationY = simd_quatf(angle: Float(45.0 * .pi/180.0), axis: SIMD3(x: 0, y: 1, z: 0))
let transform = Transform(rotation: rotationY, translation: translation)
boxEntity.transform = transform
}
}
By now, a Vision Pro engineer answered my post on Apple's developer forum, and found a workaround. Here is the tread:
Thanks for the detailed post. It makes it so much easier to help you. I think the physics simulation works, but the first few frames are being dropped. To prove this, I added a slight delay to enabling physics on the box and observed the expected physics behavior. Try this to see what I saw.
Task { @MainActor in
try await Task.sleep(nanoseconds: 3_000_000_000)
boxEntity.physicsBody = PhysicsBodyComponent(massProperties: .default,
material: PhysicsMaterialResource.generate(friction: .infinity, restitution: 0.8),
mode: .dynamic)
}
Please file a bug using feedback assistant so our teams can investigate further. In the meantime you can work around this by adding the PhysicsBodyComponent in a Task (no additional delay needed).
Task { @MainActor in
boxEntity.physicsBody = PhysicsBodyComponent(massProperties: .default,
material: PhysicsMaterialResource.generate(friction: .infinity, restitution: 0.8),
mode: .dynamic)
}