79730420

Date: 2025-08-09 04:29:45
Score: 0.5
Natty:
Report link

Thanks to @wildpeaks' answer, I have implemented this idea that works for my project (iOS13+ API, RealityKit ARView), here's the code snippet without the business logics:

// Check if the entity is in screen every 0.5s
    func startTrackingAnchorEntities() {
        anchorCheckTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] timer in
            self?.checkForNewAnchors(timer: timer)
        }
    }

    private func checkForNewAnchors(timer: Timer) {
        // Check if there is an anchor, you may do additional checks here for the right entity(names, children, etc.)
        guard let entity = self.scene.anchors.first {
            print("❌ Missing required objects - entity: \(self.scene.anchors.first != nil)")
            return
        }
        
        // Get current active camera
        let cameraTransform = self.cameraTransform
        print("📱 Camera Transform - Position: \(cameraTransform.translation), Rotation: \(cameraTransform.rotation)")
        
        // Prevent checking with the initial frame camera positions that often just passes
        if (cameraTransform.translation == SIMD3<Float>(0,0,0)) {
            print("⚠️ Camera at origin (0,0,0), skipping...")
            return
        }
             
        // Convert world position to camera space
        let cameraAnchorEntity = AnchorEntity(world: Transform(scale: .one, rotation: cameraTransform.rotation, translation: cameraTransform.translation).matrix)
        
        // Get the entity's position
        let entityPosition = entity.position(relativeTo: cameraAnchorEntity)
        print("🔍 Entity relative position: \(bubblePosition)")
        
        // IMPORTANT! Get world position for projection, else the projected point becomes super big
        let worldPosition = entity.convert(position: .zero, to: nil)
        
        // Project bubble position to screen space
        guard let projectedPoint = self.project(worldPosition) else {
            print("❌ Failed to project entity position to screen space")
            return
        }
        print("📍 Projected point on screen: \(projectedPoint)")
        print("📱 Screen bounds: \(self.bounds)")
        print("🌍 World position used for projection: \(worldPosition)")
        
        // Check if the projected point is within screen bounds
        guard self.bounds.contains(projectedPoint) else {
            print("⚠️ Entity outside screen bounds")
            return
        }
        
        print("✅ Entity visible! Scene position: \(entity.scenePosition), Camera position: \(cameraTransform.translation)")

        // Stop the timers after detecting the visible bubble
        timer.invalidate()
        anchorCheckTimer = nil

        // Do whatever you need to do afterwards
    }

What's new and what I noticed are:

  1. The idea to use this function is to call it in your ARView's set up function. For my use case, I first load an ARWorldMap then I call this function, it runs fine in parallel without interfering with the relocalization progress for those whom may concern.

  2. the .z thing @JoeySlomowitz mentioned does still persists when I'm working on this issue. So I removed it and it seems to still work like a charm.

  3. I used ARView.cameraTransform which is a newer way to get active camera position in addition to session.currentFrame.camera You may find documentation about it here.

  4. The tricky part is the relative position space, make sure everything is relative to the same position space.

Reasons:
  • Blacklisted phrase (0.5): Thanks
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @wildpeaks'
  • User mentioned (0): @JoeySlomowitz
  • Low reputation (0.5):
Posted by: MohaElder