Do not perceive iOS RealityKit’s collision detection

Do not perceive iOS RealityKit’s collision detection


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 beneath, 3 entities are arrange:
A board, a hard and fast field and a transferring field.
The board and the first field do not transfer, whereas the 2nd field strikes in direction of the first field.
All 3 entities have a collisionShape.
As a result of Physics simulation will not be used, each bins have their collision mode set to .set off.
Each bins belong to the identical CollisionGroup, and their collision filter is ready 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 direction of the first one till each are on the similar place. No collision is logged. I anticipated that the collision between each bins can be detected.

If setting of the collision filter of a field is out commented, the next is logged when the app begins (the numerous 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 may be detected, however a collision between each bins will not be. 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?
    personal 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.title) and (b.title)")
        }
    }

    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(title: "Fastened field")
            board.addChild(box1)
            
            movingBox = makeBox(title: "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, peak: boardHeight, depth: 1.0)
        var materials = UnlitMaterial(); materials.coloration.tint = .pink
        let boardEntity = ModelEntity(mesh: mesh, supplies: [material])
        boardEntity.title = "board"
        boardEntity.generateCollisionShapes(recursive: false)

        boardEntity.remodel.translation = [0, 0, -3]
        return boardEntity
    }
    
    func makeBox(title: String) -> ModelEntity {
        let mesh = MeshResource.generateBox(width: 0.2, peak: boxHeight, depth: 0.3)
        var materials = UnlitMaterial(); materials.coloration.tint = .inexperienced
        let boxEntity = ModelEntity(mesh: mesh, supplies: [material])
        boxEntity.title = title
        
        // To place the field onto the board, transfer it up by half peak of the board and half peak of the field
        let y_up = boardHeight/2.0 + boxHeight/2.0
        boxEntity.place = SIMD3(0, y_up, 0)
        
        // Permit to detect collisions between bins 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
    }

}

Leave a Reply

Your email address will not be published. Required fields are marked *