ECS custom component not being found when interact with it by a gesture

Hello, I am working in a custom component using ECS. My custom component is simple, has only an enum property and a float value. The System for this component just change the entity mesh color and put it to rotate.

My component is being added in runtime on the reality view scene that I am working. The entities are being added correctly on scene, the colors are changing and it's rotating. But when I try to get this custom component by the tap gesture, it's saying that the entity does not have the component.

I am adding the componets with this method:

...
RealityView { content in
            if let mySceneEntity = try? await Entity(named: "MyScene", in: realityKitContentBundle) {              
                await MM_InitializePointsOfInterest(sceneEntity: mySceneEntity, data: modelData)
...

And the method that instatiate it is this:

func MM_InitializePointsOfInterest(sceneEntity: Entity, data: ModelData) async {   
    if let pinsGroup = await sceneEntity.findEntity(named: PointOfInterestSystem.pinsGroupID) {
        //find for the parent that will store the points of interest entities
        if let pinObject = try? await Entity(named: PointOfInterestSystem.pointOfInterestID, in: realityKitContentBundle) {
            
            //The json file do not have the UUID on it, so we generate it in when start to use
            data.pointsOfInterest.generateUUIDs()
            
            for poiData in data.pointsOfInterest.pointsList {
                let pin = await pinObject.clone(recursive: true)
                
                let pos = SIMD3<Float>(poiData.location[0], poiData.location[1], poiData.location[2]) / 100 //convert to cm
                await pin.setPosition(pos, relativeTo: nil)
                
                let poiComponent = PointOfInterestComponent(rotationSpeed: 0.5, type: poiData.type)
                
                await pin.components.set(poiComponent)
                await print("Has Component: \(pin.components.has(PointOfInterestComponent.self))")
                await pinsGroup.addChild(pin)
                
                print("Pin added at position: \(pos)")
            }
        }
    }

I had some prints to debug, and they are working, showing that the entity was added to scene and that has the custom component that I made.

But here, When I try to get the gesture:

RealityView {
 ...
}.gesture(
SpatialTapGesture()
            .targetedToAnyEntity()
            .onEnded { value in
                print("Tap Gesture detected.")
                
                if let poiComp = value.entity.components[PointOfInterestComponent.self] {
                    print("Point of Interest Component Id: \(poiComp.id)")
                    let p : PointOfInterest = modelData.pointsOfInterest.pointsList.first(where: {$0.id == poiComp.id})!
                    print(p.name)
                } else {
                    print("Point Of Interest Component NOT FOUND!")
                }
                
                let curScale = value.entity.transform.scale.x
                value.entity.transform.scale = curScale > 1 ? SIMD3(1,1,1) : SIMD3(1.4, 1.4, 1.4)
            }              

Is printing that the Point of Interest Component NOT FOUND!

But the entities are on the scene rotating and with the colors that was set by the system of the ECS.

If I add my custom component in an element that Already exists on scene (In reality composer pro) and try to access, I find it.

Hello,

It seems likely that the entity you are tapping on does not actually contain a "PointOfInterestComponent". I recommend that you give your entities names for debugging purposes. Then, in your tap gesture, log the name of the entity, does it match the name that you are expecting?

Hey @gchiste thanks for your answer. So, I made the test that you asked, and the answer is NO, the name that I add on the function that instantiate the entities is not the same as the name of the entity that the gesture get.

I made another test already, that was instead of add the entities on my func, I return an array of entities with all the elements. And when I do it:

   if let pinsGroup = erzbergSceneEntity.findEntity(named: PointOfInterestSystem.pinsGroupID) {
                    x.forEach{ e in
                        print(e.components.has(PointOfInterestComponent.self))
                        print(e.name)
                        pinsGroup.children.append(e)
                    }
                }

It shown the name that I added and the component on it, but still seeing a different name when I interact with the entity on scene by TAP Gesture. I don't know if because I am adding the elements inside of my reality view if. I need to refresh something. Did you have any tip?

Full Reality View code:

  var body: some View {
        @Bindable var modelData = modelData
        
        RealityView { content in
            // Add the initial RealityKit content
            if let sceneEntity = try? await Entity(named: "EScene", in: realityKitContentBundle) {
                                        
                // Add an ImageBasedLight for the immersive content
                guard let resource = try? await EnvironmentResource(named: "ImageBasedLight") else { return }
                let iblComponent = ImageBasedLightComponent(source: .single(resource), intensityExponent: 0.25)
                sceneEntity.components.set(iblComponent)
                sceneEntity.components.set(ImageBasedLightReceiverComponent(imageBasedLight: sceneEntity))
                
                print("Adding Points Of Interest...")
                let x = await MM_InitializePointsOfInterest(sceneEntity: sceneEntity, data: modelData)
                               
                if let pinsGroup = sceneEntity.findEntity(named: PointOfInterestSystem.pinsGroupID) {
                    x.forEach{ e in
                        print("Has POI Component? \(e.components.has(PointOfInterestComponent.self)) - with name: \(e.name)")
                        pinsGroup.children.append(e)
                    }
                }
                content.add(sceneEntity)
            }
        }
        .gesture(tap)
    }
    
    var tap: some Gesture {
        SpatialTapGesture()
            .targetedToAnyEntity()
            .onEnded { value in
                
                print("Tap Gesture detected on: \(value.entity.name).")
                                
                if let poiComp = value.entity.components[PointOfInterestComponent.self] {
                    print("Point of Interest Component Id: \(poiComp.id)")
                    //let p : PointOfInterest = modelData.pointsOfInterest.pointsList.first(where: {$0.id == poiComp.id})!
                    //print(p.name)
                } else {
                    print("Point Of Interest Component NOT FOUND!")
                }
                
                let curScale = value.entity.transform.scale.x
                value.entity.transform.scale = curScale > 1 ? SIMD3(1,1,1) : SIMD3(1.4, 1.4, 1.4)
            }
    }

I discovered WHY my Gesture tap wasn't get the component. For some reason, when I clone the Entity that I want to instantiate and add my custom component, It's creating a ROOT element over the cloned entity.

To be more clear: This print:

print("Tap Gesture detected on: \(value.entity.name) parent with name: \(value.entity.parent?.name)")

Generates this output:

Tap Gesture detected on: PointOfInterest parent with name: Optional("21BB3CB1-8EAC-4645-B154-C8D15ACB8858")

WHERE the name of my cloned component was set to it's UUID string v alue. So It's visible that the gesture was got on the original root element (where the collider and input components was added) but my component was added one level above.

Someone could explain to me why when I cloned:

 let pin = await pinObject.clone(recursive: true)
 pin.name = poiData.id 

the structure of my entity changed to have a new ROOT element?

Hello, I’d recommend putting together a full project at this point and making it available for download, this would enable me (or anyone else following along) to aid you in identifying where the bug is :)

Did you register the custom components (with "PointOfInterest.registerComponent()") before loading the scene? If the scene is loaded before the components are registered, RealityKit won't find the type and will discard the serialized custom component.

I have the same problem. I registered my component, and I add it to the entity via code. If I print the component right after adding it, I do get the component including its values. But if I receive the tap gesture, the component is gone. I have registered the component on app startup, so this should not be the issue. Any ideas why the component gets lost when a tap gesture is performed? This is super confusing.

ECS custom component not being found when interact with it by a gesture
 
 
Q