How can I limit selection range of the laserPointer used by WebXRController PointerSelection?

I’ve figured out how to get the currently selected mesh using .getMeshUnderPointer for each controller. But it has super long range (it can basically select things across the room) when I want to limit what the player can select to whatever is near them (maybe 3m max?)

My gut says raySelectionPredicate would work (or I could just draw my own ray) if I can get the position of the selectionMesh, but from what I can see I can only change the colors of the laser pointer and selection mesh. How can I get the selectionMesh? it’s locked in a private object inside controllers in xrHelper.pointerSelection

The ray length is set automatically, based on the meshes the ray collides against in the scene.
If it doesn’t hit anything it will be 1 unit long (i.e. 1 meter long in XR).

Do you want to set the length yourself?

Okay so I hacked together a quick playground with a simplified version of what I got.

Basically, I have the player in an area that’s surrounded by a mesh skybox. I’m not sure if we’re talking about the same laser pointer, for my Meta Quest 2 the laser pointer basically can select the skybox even though I’m more than 1m away from it. Same for the cylinder and cone in the red area. I can select them even though I’m really far away from them.

I feel like the button press observable is very useful if you want to build a UI in VR to click on, but I don’t want users to be clicking on things super far away from them cause that would be confusing. I was hoping there’s a way to get the selectionMesh (it’s the red dot colored by xr.pointerSelection.selectionMeshDefaultColor) but I can only access the inputSource.pointer (controllers L and R), which I’m assuming is the player’s hand.

The 1 meter length is when there is no mesh to be picked by the ray coming from your controller.
You can define meshes as “pickable”, i.e. - can be picked by the ray, or not pickable. there is an isPickable variable that you can set. Otherwise you can set the selection predicate yourself. the predicate is a function running on every mesh in your scene, returning true to meshes that should be picked, and false to meshes that aren’t. A simple predicate could be:

const predicate = (mesh) => === "OnlyMeshToBePicked"

This will pick mesh(es) with this specific name. of course it can be more complex. The default one returns true to meshes that are enabled, visible, and pickable.

You can set the predicate on the scene’s level (to work in both desktop and XR scenarios) or when initializing the XR session to have different meshes picked in XR and on the desktop.

I hope it makes sense!

I get it yeah, I can make things like the skybox mesh be isPickable false and use a predicate like mesh position is < 1m away from camera position.
This would work for small objects for the player to interact with. The logic would be trippy if the mesh was larger (like an arch or something) where the position might be not in the object’s center of gravity.

You can also pass maxPointerDistance instead of adjusting the predicate, if you want to limit the ray to only work certain amount of units away from you. This is a part of the options that are passed to the pointer selection option when initializing the XR experience.


maxPointerDistance did exactly as I needed! I was worried it’d affect how far teleportation works, but glad it doesn’t. The laser beam is visually shorter though; ideally I’d just want it to look the same but only select things much closer, but this will do!

Thanks Raanan! You’re dependable as always!

1 Like

great! glad it worked :slight_smile:

if there is anything that you want to change visually and is not configurable let me know. i will be happy to add more configuration options if needed!

1 Like