I'm trying to detect when two entities collide. The following code shows a very basic set-up. How do I get the upperSphere to move? If I set its physicsBody.mode to .dynamic it moves due to gravity (and the collision is reported), but when in kinematic mode it doesn't respond to the impulse:
struct CollisionView: View {
@State var subscriptions: [EventSubscription] = []
var body: some View {
RealityView { content in
let upperSphere = ModelEntity(mesh: .generateSphere(radius: 0.04))
let lowerSphere = ModelEntity(mesh: .generateSphere(radius: 0.04))
upperSphere.position = [0, 2, -2]
upperSphere.physicsBody = .init()
upperSphere.physicsBody?.mode = .kinematic
upperSphere.physicsMotion = PhysicsMotionComponent()
upperSphere.generateCollisionShapes(recursive: false)
lowerSphere.position = [0, 1, -2]
lowerSphere.physicsBody = .init()
lowerSphere.physicsBody?.mode = .static
lowerSphere.generateCollisionShapes(recursive: false)
let sub = content.subscribe(to: CollisionEvents.Began.self, on: nil) { _ in print("Collision!") }
subscriptions.append(sub)
content.add(upperSphere)
content.add(lowerSphere)
Task {
try? await Task.sleep(for: .seconds(2))
print("Impulse applied")
upperSphere.applyLinearImpulse([0, -1, 0], relativeTo: nil)
}
}
}
}
Furthermore, if I set up the physicsMotion with a velocity: upperSphere.physicsMotion?.linearVelocity = [0,-1,0]
It moves down, but no collision is registered.
You just need to switch ball's physics body mode from .static
to .dynamic
. Kinematic mode is used only when the user needs to manually control a physics body movement.
import SwiftUI
import RealityKit
struct CollisionView : View {
@State var subscriptions: [EventSubscription] = []
let upperBall = ModelEntity(mesh: .generateSphere(radius: 0.12))
let lowerBall = ModelEntity(mesh: .generateSphere(radius: 0.12))
var body: some View {
RealityView { rvc in
upperBall.position = [0,2,-2]
upperBall.physicsBody = .init()
upperBall.physicsBody?.mode = .static
upperBall.generateCollisionShapes(recursive: false)
lowerBall.position = [0,1,-2]
lowerBall.physicsBody = .init()
lowerBall.physicsBody?.mode = .static
lowerBall.generateCollisionShapes(recursive: false)
rvc.add(upperBall)
rvc.add(lowerBall)
let sub = rvc.subscribe(to: CollisionEvents.Began.self) { _ in
print("Collision detected")
}
subscriptions.append(sub)
Task {
try await Task.sleep(for: .seconds(1))
upperBall.physicsBody?.mode = .dynamic
}
}
}
}
@main struct ColliderApp : App {
var body: some Scene {
ImmersiveSpace() {
CollisionView()
}
}
}