I’m attempting to detect collisions between two RealityKit entities, however the outcomes are surprising.
I thus created a minimal instance. Within the iOS app under, 3 entities are arrange:
A board
, a set field
and a transferring field
.
The board and the first field do not transfer, whereas the 2nd field strikes in the direction of the first field.
All 3 entities have a collisionShape
.
As a result of Physics simulation just isn’t used, each packing containers have their collision mode set to .set off
.
Each packing containers belong to the identical CollisionGroup
, and their collision filter is about to this group.
A CollisionManager
subscribes to the start of collision occasions. If a collision is detected, the collision is logged.
When the app is began, the 2nd field is transferring in the direction of the first one till each are on the identical place. No collision is logged. I anticipated that the collision between each packing containers can be detected.
If setting of the collision filter of a field is out commented, the next is logged when the app begins (the various RealityKit logs are omitted):
collision started between board and Fastened field
collision started between Fastened field and board
collision started between board and Shifting field
collision started between Shifting field and board
Clearly, collision might be detected, however a collision between each packing containers just isn’t. However why?
Right here is my code:
//
// CollisionApp.swift
// Collision
//
// Created by Reinhard Männer on 31.03.25.
//
import SwiftUI
@predominant
struct CollisionApp: App {
var physique: some Scene {
WindowGroup {
ContentView()
}
}
}
//
// CollisionManager.swift
// Collision
//
// Created by Reinhard Männer on 31.03.25.
//
import Mix
import Basis
import RealityKit
class CollisionManager {
var movementTimer: Timer?
non-public var updateVehicleCollisionSubscription: Cancellable?
func startVehicleCollisionTrigger(scene: RealityKit.Scene) {
updateVehicleCollisionSubscription = scene.subscribe(to: CollisionEvents.Started.self) { occasion in
let a = occasion.entityA
let b = occasion.entityB
print("collision started between (a.identify) and (b.identify)")
}
}
func startMovement(entity: Entity) {
movementTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
if entity.place.x > 0 {
entity.place.x -= 0.02
} else {
timer.invalidate()
self.movementTimer = nil
}
}
}
}
//
// ContentView.swift
// Collision
//
// Created by Reinhard Männer on 31.03.25.
//
import RealityKit
import SwiftUI
struct ContentView: View {
let collisionManager = CollisionManager()
let boardHeight: Float = 0.1
let boxHeight: Float = 0.3
var physique: some View {
var movingBox: Entity?
RealityView { content material in
let board = makeBoard()
content material.add(board)
let box1 = makeBox(identify: "Fastened field")
board.addChild(box1)
movingBox = makeBox(identify: "Shifting field")
movingBox?.place.x = 0.8
board.addChild(movingBox!)
}
replace: { content material in
let scene = content material.entities.first?.scene
collisionManager.startVehicleCollisionTrigger(scene: scene!)
collisionManager.startMovement(entity: movingBox!)
}
}
func makeBoard() -> ModelEntity {
let mesh = MeshResource.generateBox(width: 2.0, top: boardHeight, depth: 1.0)
var materials = UnlitMaterial(); materials.colour.tint = .pink
let boardEntity = ModelEntity(mesh: mesh, supplies: [material])
boardEntity.identify = "board"
boardEntity.generateCollisionShapes(recursive: false)
boardEntity.rework.translation = [0, 0, -3]
return boardEntity
}
func makeBox(identify: String) -> ModelEntity {
let mesh = MeshResource.generateBox(width: 0.2, top: boxHeight, depth: 0.3)
var materials = UnlitMaterial(); materials.colour.tint = .inexperienced
let boxEntity = ModelEntity(mesh: mesh, supplies: [material])
boxEntity.identify = identify
// To place the field onto the board, transfer it up by half top of the board and half top of the field
let y_up = boardHeight/2.0 + boxHeight/2.0
boxEntity.place = SIMD3(0, y_up, 0)
// Enable to detect collisions between packing containers solely and to set off code execution.
boxEntity.generateCollisionShapes(recursive: false)
boxEntity.collision!.mode = .set off
let collisionGroup = CollisionGroup(rawValue: 1 << 0)
let filter = CollisionFilter(group: collisionGroup, masks: collisionGroup)
boxEntity.collision!.filter = filter
return boxEntity
}
}