A scene usually has several things that want to know what sits under the pointer: a formation slot to glow, the ground an aim lands on, a unit to outline. Each one casting its own ray means several raycasts per frame and several answers to the same question. PointerProbe is one raycast the whole scene shares, and it knows when the pointer is on UI so none of those readers has to.
RaycastAll per frame from the pointer, with the union of every reader's layers, sorted by distance.Add PointerProbe to a scene object and hand it to the readers (a scene service provider is the natural owner). Readers register the layers they care about once:
_probe.IncludeLayer(slotLayer);
_probe.IncludeMask(groundMask);// the nearest hit carrying a component (or an interface) on itself or a parent
if (_probe.TryGetFirst(out FormationSlot slot, out RaycastHit hit)) { ... }
if (_probe.TryGetFirst(out IWorldDropTarget target)) { ... }
// the nearest hit on a layer mask
if (_probe.TryGetFirst(groundMask, out RaycastHit ground)) { ... }
// the nearest collider changed (including to or from none)
_probe.TopChanged += Refresh;
// this frame's pointer in a panel's coordinates
Vector2 inPanel = _probe.PointerInPanel(root.panel);ScreenPosition, PrimaryPressedThisFrame, PrimaryHeld and PrimaryReleasedThisFrame describe the pointer this frame. OverScreenUI says whether the probe skipped the cast.
The gate the probe uses is public:
if (LunaUIManager.Instance.IsPointerOverView(screenPosition)) return;Every UIView registers with the manager on construction, so the answer follows views as they open and close. Use it in any scene reader that must not act while the pointer is on the HUD (click-to-move, hover highlights).
Settings
Theme
Light
Contrast
Material
Dark
Dim
Material Dark
System
Sidebar(Light & Contrast only)
Font Family
DM Sans
Wix
Inclusive Sans
AR One Sans
Direction