Search code examples
aframe

A-Frame: parent's raycaster-intersected-cleared triggered if no intersection with children


I'm implementing a feature to get coordinate of an a-sky while moving the VR controller.

<a-scene scenelistener>
  <a-sky
    id="map-sky"
    color="#222"
    radius="700"
    rotation="0 45 0"
    rotation-control
    raycaster-listen
    class="ray-castable"
  >
    <a-entity
      id="country-tiles"
      country-tiles
      scale="1 1 1"
      rotation="0 90 0"
    ></a-entity>
  </a-sky>
  ... // Oculus entities
</a-scene>

a-sky and its children is listening for raycasting, and print out the console logging

AFRAME.registerComponent("raycaster-listen", {
  init: function() {
    this.el.addEventListener("raycaster-intersected", evt => {
      console.log(`raycaster ${this.el.id} intersected!!!`);
    });
    this.el.addEventListener("raycaster-intersected-cleared", evt => {
      console.log(`raycaster ${this.el.id} cleared!!!`);
    });
  }
});

RESULT: while moving in and out the children country-tiles, raycaster-intersected-cleared event is triggered from the children and also its parent map-sky, mean A-Frame cannot get the intersections between a-sky and the raycasting VR controller.

raycaster  intersected!!!
raycaster map-sky intersected!!!
// Moving out the tile
raycaster  cleared!!!
raycaster map-sky cleared!!!

You can check on this Glitch

NOTE: since I am developing for VR controller, therefore please use the WebXR emulator extension for interaction


Solution

  • It turns out that raycaster-intersected-cleared event from parent element is fired but it does not mean that it is not intersected anymore. To confirm if it has been still intersected I have to check if getIntersection result is NULL.

    AFRAME.registerComponent("raycaster-listen", {
      init: function() {
        this.el.addEventListener("raycaster-intersected", evt => {
          console.log(`raycaster ${this.el.id} intersected!!!`);
          this.raycaster = evt.detail.el;
        });
        this.el.addEventListener("raycaster-intersected-cleared", evt => {
          if (this.raycaster) {
            const intersection = this.raycaster.components.raycaster.getIntersection(this.el);
            if (!intersection) {
              console.log(`raycaster ${this.el.id} cleared!!!`);
            }
          }
        });
      }
    });