So I have the default scene for an ImmersiveView that has two plain spheres. I am moving one of them with my game controller.
import SwiftUI
import RealityKit
import RealityKitContent
import GameController
struct ImmersiveView: View {
@State var sphereX: Float = 0.5
@State var sphereY: Float = 1.5
@State var sphereZ: Float = -1.5
var body: some View {
RealityView { content in
if let scene = try? await Entity(named: "Immersive", in: realityKitContentBundle) {
content.add(scene)
}
Task.detached {
for await _ in NotificationCenter.default.notifications(named: .GCControllerDidConnect) {
Task { @MainActor in
for controller in GCController.controllers() {
controller.extendedGamepad?.valueChangedHandler = { pad, _ in
Task { @MainActor in
let speed: Float = 0.1
sphereX += pad.leftThumbstick.xAxis.value * speed
sphereY += pad.leftThumbstick.yAxis.value * speed
sphereZ -= pad.rightThumbstick.yAxis.value * speed
}
}
}
}
}
}
} update: { content in
guard let scene = content.entities.first,
let movableSphere = scene.findEntity(named: "Sphere_Right") else {
return
}
movableSphere.position.x = sphereX
movableSphere.position.y = sphereY
movableSphere.position.z = sphereZ
}
}
}
How can I detect that the movable sphere collides with the other sphere?
Let's assume that Reality Composer Pro scene contains a cube that sits above a sphere primitive. Both models must have the Physics Body
component (first is dynamic and second is static) and Collision
component. Try the following code if you're planning to detect a collision between 3D objects.
import SwiftUI
import RealityKit
import RealityKitContent
struct ContentView : View {
@State private var subs: [EventSubscription] = []
var body: some View {
VStack {
RealityView { content in
if let scene = try? await Entity(named: "Scene", in: realityKitContentBundle) {
content.add(scene)
}
} update: { content in
if let cube = content.entities.first?.findEntity(named: "Cube") as? ModelEntity {
let event = content.subscribe(to: CollisionEvents.Began.self, on: cube) { ce in
print("Collision between \(ce.entityA.name) and \(ce.entityB.name) is occured")
}
DispatchQueue.main.async {
subs.append(event)
}
}
}
}
}
}
#Preview {
ContentView()
}
Or create a scene programmatically from scratch:
struct ContentView : View {
@State private var subs: [EventSubscription] = []
var body: some View {
VStack {
RealityView { content in
let ball = ModelEntity(mesh: .generateSphere(radius: 0.15))
ball.generateCollisionShapes(recursive: false)
ball.name = "Sphere"
content.add(ball)
let cube = ModelEntity(mesh: .generateBox(size: 0.25))
cube.generateCollisionShapes(recursive: false)
cube.components[PhysicsBodyComponent.self] = .init()
cube.position = [0.259, 2.0, 0.0]
cube.name = "Cube"
content.add(cube)
let event = content.subscribe(to: CollisionEvents.Began.self, on: cube) { ce in
print("Collision between \(ce.entityA.name) and \(ce.entityB.name) is occured")
}
Task {
subs.append(event)
}
}
}
}
}