Skip to main content
dello32
Inspiring
March 28, 2025
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
dello32
dello32Answer
Inspiring
April 2, 2025
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

atlantikaryan
Up and Coming
March 29, 2025

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
Honored Contributor
March 31, 2025

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.

GitHub: https://github.com/Gausroth/HorizonWorldsTutorials.git Discord: https://discord.gg/hNyDQwdw4N YouTube: https://www.youtube.com/@GausRothTutorials
Shards632
Honored Contributor
March 31, 2025

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

June Programming Calendar
gausroth
Honored Contributor
March 29, 2025

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"))
}

 

GitHub: https://github.com/Gausroth/HorizonWorldsTutorials.git Discord: https://discord.gg/hNyDQwdw4N YouTube: https://www.youtube.com/@GausRothTutorials
dello32
dello32Author
Inspiring
March 29, 2025

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
Honored Contributor
March 29, 2025

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.

GitHub: https://github.com/Gausroth/HorizonWorldsTutorials.git Discord: https://discord.gg/hNyDQwdw4N YouTube: https://www.youtube.com/@GausRothTutorials
dello32
dello32Author
Inspiring
March 30, 2025

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
Honored Contributor
March 31, 2025

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
}
GitHub: https://github.com/Gausroth/HorizonWorldsTutorials.git Discord: https://discord.gg/hNyDQwdw4N YouTube: https://www.youtube.com/@GausRothTutorials
dello32
dello32AuthorAnswer
Inspiring
April 2, 2025
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 ðŸ˜‰