Forum Discussion

dello32's avatar
dello32
Member
9 months ago
Solved

RaycastGizmo with objectTag

I'm trying to use RayCastGizmo with objectTag, but it seems like the tag set in the interface isn't being used in the script.
 
Example:
const options = {
  layerType: hz.LayerType.Objects,
  maxDistance: 10
};
const hit = this.rayCaster!.raycast(origin, direction);
 
Will hits all objects, not just the ones with the objectTag set in the RayCastGizmo.
 
Has anyone else run into this? Has this feature been removed
  • I'm coming back to try and wrap up this discussion.
     
    • The original question:
    Does the "objectTag" option set in the RayCastGizmo interface get used in the script?
    ANSWER: no, it's not taken into account.
     
    • My apologies:
    Gausroth actually pointed me in the right direction from the start. I just didn’t understand how to access hit.target (my IDE didn’t show it — I just needed to cast hit properly to EntityRaycastHit).
     
    • Conclusion:
    Here's a small function that might help clarify things and be useful to others.
     
    export function rayCastObjectByTag(rayCaster: hz.RaycastGizmo, direction: hz.Vec3, tag: string, maxDist = 10): hz.RaycastHit | null {
      const pOrigin = rayCaster.position.get();
      const options = { layerType: hz.LayerType.Both, maxDistance: maxDist };
      const hit = rayCaster.raycast(pOrigin, direction, options);
      if (hit && hit.targetType === hz.RaycastTargetType.Entity) {
        const entity = hit.target;
        if (entity.tags.contains(tag)) return hit;
      }
      return null;
    }
     
    Thanks a lot for your patience 😉

12 Replies

  • I ran into something similar today when I had set a collider to filter on Players. The RayCastGizmo had an objectTag but was still registering hits against that collider (that had no Tag).

    Obviously that collider was also not a Player, so there may be a couple of unexpected things going on here.

    • gausroth's avatar
      gausroth
      Mentor

      The ray cast will only hit what its "Collide With" is set too. So, either Player or Object. If you have it set to Objects Tagged or Both and give it a tag it will return every collideable object that it hits and does not have that tag as a Static Object even if the object is animated. If you leave the tag empty, it will register all objects as entity if its motion is set to animated or interactive or static if its motion is set to none.

      • Shards632's avatar
        Shards632
        Mentor

        raycasts will return all non-static entities as HitEntity results if the raycast has _no_ tag filter?  Is this new?

  • I'm not sure if your missing code or if you just did not paste it all here. but it should look something like this. The raycast will return a hit on any collidable object. However, there are ways to narrow it down to the tagged object

    update({ deltaTime }: { deltaTime: number }) {
         // stops code from running every frame if object is not being grabbed
         if (!this.isGrabbed) return;
    
         // we check if the raycast has been assigned in the properties panel
         if (this.props.rayCast) {
              const hit = this.props.rayCast.as(RaycastGizmo).raycast(this.entity.position.get(), this.entity.forward.get(), {
                   layerType: LayerType.Objects,
                   maxDistance: 5
              });
    
              // check if we hit an collideable object
              if (hit) {
                   const hitPoint = hit.hitPoint;
    
                   // checkf if the hit object is the correct target type
                   if (hit.targetType === RaycastTargetType.Entity) {
                        // check if the target has a tag named "tag"
                        if(hit.target.tags.contains("tag")){
                             // hit an object with a tag named "tag"
                        }
                   }
              }
         }
         else (console.warn("rayCast is null or missing"))
    }

     

    • dello32's avatar
      dello32
      Member

      Thanks for the reply. You give me the solution! 😉

      But, this is strange to have an interfac property not used by the raycastGizmo. 

      Thanks!

      • gausroth's avatar
        gausroth
        Mentor

        I could be just something left over from code blocks. But you may not have to check for objects tagged either. Test and see if it returns all objects that are of the target type or just the tagged objects.

    • dello32's avatar
      dello32
      Member

       

      To clarify for everyone: there is no hit.target!!!

      According to the documentation, there is currently nothing available to replace the raycast object tag:
      raycast(origin: Vec3, direction: Vec3, options?: {

              layerType?: LayerType;
              maxDistance?: number;
          }): RaycastHit | null;
       
      And RaycastHit is just an object that inherits from BaseRaycastHit:
      declare type BaseRaycastHit = {
          distance: number;
          hitPoint: Vec3;
          normal: Vec3;
      };

      So yeah, it's a bit shameful because from my point of view, Meta actually lost features when switching to TypeScript 😓

       

       

       

      • gausroth's avatar
        gausroth
        Mentor

        What do you mean there is no hit.target? Once you verify hit is an entity, you get the target.

  • What i mean is, there is no method or attribute 'target' on a hit objet (BaseRaycastHit ). So, it's not possible to make:

    hit.target

     

    • gausroth's avatar
      gausroth
      Mentor

      not sure what you mean.

      hit refers to the object that was hit by the raycast. There are three types of objects the raycast (static, entity, player) may have hit. So, if there was a hit you must check.

      if (hit.targetType === RaycastTargetType.Static) {
           //A static object
      }
      
      if (hit.targetType === RaycastTargetType.Entity) {
           //A non static object
      }
      
      if (hit.targetType === RaycastTargetType.Player) {
           //A player
      }

       

      static objects are the only one you cannot get the target. The other two you can:

      if (hit.targetType === RaycastTargetType.Static) {
           // A static object
           // throws an error '(TS) Property 'target' does not exist on type 'StaticRaycastHit'.
           const obj = hit.target
      }
      
      if (hit.targetType === RaycastTargetType.Entity) {
           // A non static object
           // Does not throw an error
           const obj = hit.target
      }
      
      if (hit.targetType === RaycastTargetType.Player) {
           // A player
           // Does not throw an error
           const obj = hit.target
      }
  • I'm coming back to try and wrap up this discussion.
     
    • The original question:
    Does the "objectTag" option set in the RayCastGizmo interface get used in the script?
    ANSWER: no, it's not taken into account.
     
    • My apologies:
    Gausroth actually pointed me in the right direction from the start. I just didn’t understand how to access hit.target (my IDE didn’t show it — I just needed to cast hit properly to EntityRaycastHit).
     
    • Conclusion:
    Here's a small function that might help clarify things and be useful to others.
     
    export function rayCastObjectByTag(rayCaster: hz.RaycastGizmo, direction: hz.Vec3, tag: string, maxDist = 10): hz.RaycastHit | null {
      const pOrigin = rayCaster.position.get();
      const options = { layerType: hz.LayerType.Both, maxDistance: maxDist };
      const hit = rayCaster.raycast(pOrigin, direction, options);
      if (hit && hit.targetType === hz.RaycastTargetType.Entity) {
        const entity = hit.target;
        if (entity.tags.contains(tag)) return hit;
      }
      return null;
    }
     
    Thanks a lot for your patience 😉