Я пытаюсь обнаружить столкновение двух объектов. Следующий код показывает очень простую настройку. Как мне заставить верхнюю сферу двигаться? Если я установлю его PhysicsBody.mode в .dynamic, он будет двигаться под действием силы тяжести (и о столкновении будет сообщено), но в кинематическом режиме он не будет реагировать на импульс:
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)
}
}
}
}
Кроме того, если я настрою PhysicsMotion со скоростью: upperSphere.physicsMotion?.linearVelocity = [0,-1,0]
Он движется вниз, но столкновения не зарегистрировано.





Вам просто нужно переключить режим физики тела мяча с .static на .dynamic. Кинематический режим используется только тогда, когда пользователю необходимо вручную управлять физическим движением тела.
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()
}
}
}
Филип, я полностью согласен, но гравитация все равно делает свое дело.
Спасибо. Еще один небольшой момент, который нужно добавить: мне нужно установить для isAffectedByGravity значение false на физическом теле, и тогда моя импульсная команда заставит его двигаться.