AFS_UX_Laser
A pointer laser as a controller ability, for distant selection and for driving UMG at range.
What it gives you
- A themed pointer beam with hover feedback
- Distance-clamped reach
- The pointer that drives world-space UI in VR
Required by
Description
The laser is a controller ability that draws a beam and reports what it hits. It does not decide what happens on hit — that belongs to the select or widget abilities — which is why it can serve both object selection and UMG interaction without knowing about either.
The beam clamps between Min Laser Length and Max Laser Length and terminates on whatever it
hits, so it reads correctly against near and far surfaces. Targets can override where the beam
appears to land through Select_HitLocationOverride, which is how a laser snaps to a control's
centre rather than wherever the raw trace struck.
Setup
- Enable
AFS_UX_Laser. - Add
BPC_ControllerAbility_Laserto the motion controller Blueprint. - Set Thickness, Color and the length limits.
Usage
Using it for selection
Pair with AFS_UX_Select. The laser supplies the trace; BPC_PawnAbility_Select resolves the target.
Using it for UI
Pair with AFM_WidgetInteraction. The laser drives the pointer index and the widget receives normal
UMG events.
Hiding it contextually
Use the blocker API — block the laser ability while an object is held so the beam does not fight the grip.

Key properties
| Property | When to change |
|---|---|
Max Laser Length | Reach; keep it to what the scene needs |
Min Laser Length | Prevents the beam collapsing on very near hits |
Thickness / Color | Appearance; match your theme |
Extending
Derive from BPC_ControllerAbility_Laser to change how the beam is drawn or what it traces against.
Example map
Used throughout Map_Examples_Select and Map_Examples_UI.
Troubleshooting
The beam passes through the target. The target's collision does not block the trace channel the laser uses.
API reference
Every blueprint asset in this plugin. Expand an asset to see its members.
Components
BPC_ControllerAbility_Laser34 members
| Kind | Name | Signature | Description |
|---|---|---|---|
| var | PointerTransformInteractionSettings | E_Pointer_TransformInteraction | What the thumbstick does to an object held out at the end of the beam: turn it about its up axis while the other axis pushes it away and pulls it back, turn it about both axes, or scale it. Set None to ignore the stick. The transform mode button steps through the modes at runtime, so this only sets the one you start in. |
| var | MaxGrabDistanceOffsetSettings | float | Furthest, in centimetres, that a remotely held object can be pushed away from the hand with the stick. The offset is clamped between zero and this value, so a smaller number keeps grabbed objects within reach. |
| var | LaserVisualInterpTimeSettings | float | Rate at which the beam's colour and thickness chase the style of whatever is being pointed at or held. Despite the name it is an interpolation speed rather than a duration, so larger values reach the new style sooner and zero leaves the beam stuck on its current appearance. |
| var | MaxInterpolationDistanceSettings | float | How far, in centimetres, the end of the beam is allowed to ease towards a new target before it is placed there outright. Keeps the beam from visibly trailing behind when the trace jumps from a near surface to a distant one. |
| var | InterpolationSpeedSettings | float | Speed at which the end of the beam eases towards the current hit point instead of snapping to it. Higher values track the trace more tightly; the smoothing itself only applies within Max Interpolation Distance. |
| var | MaxLaserLengthSettings | float | Reach of the pointer in centimetres. Nothing beyond this distance can be hovered, selected or gripped, and with no hit the beam is drawn out to this length. |
| var | Mapping Contexts DefaultInput | ST_MappingContext_Side | Input mapping contexts applied for the left and right hand, giving the laser its select, grip and transform bindings. The ability's own hand side decides which of the two is used. |
| var | Mapping Contexts No GrabInput | ST_MappingContext_Side | Input mapping contexts held while the laser is gripping nothing, so the stick and buttons drive the pointer itself. Removed as a grip is taken and added again by Grabbing Actor Release. |
| var | MappingContextGripSnappedInput | ST_MappingContext_Side | Input mapping contexts added while the laser is latched onto something or holding an object snapped to the controller. Swapped back for the no-grab contexts when the grip is released. |
| var | MappingContextGrabRemoteInput | ST_MappingContext_Side | Input mapping contexts used while an object is carried out at the end of the beam rather than snapped to the hand, so the stick can rotate, scale and push the object about. Removed again on release. |
| var | LaserStyle_LatchLaser Style | Struct_Laser_Style_Item | Colour and end radii the beam eases to while it is latched onto something. Picked by Get Desired Laser Style for as long as the held grip is a latch, whatever the beam is pointing at. |
| var | LaserStyle_PickupLaser Style | Struct_Laser_Style_Item | Colour and end radii the beam eases to while it is carrying a pickup, whether that object is snapped to the hand or held out at a distance. |
| var | LaserStyle_SelectPressedLaser Style | Struct_Laser_Style_Item | Colour and end radii used while the select button is down and nothing is gripped, so the beam reacts to the press even when it is pointing at empty space. |
| var | LaserStyle_DefaultLaser Style | Struct_Laser_Style_Item | Colour and end radii of the resting beam: nothing gripped, nothing interactive under the pointer and select not pressed. While the ability is hidden the beam falls back to a fixed transparent grey instead of this. |
| var | LaserStyle_Hover_SelectLaser Style | Struct_Laser_Style_Item | Colour and end radii used while the beam is over an actor that offers a selectable interaction and the button has not been pressed yet. |
| var | LaserStyle_Hover_PickupLaser Style | Struct_Laser_Style_Item | Colour and end radii meant for hovering something that can be picked up. Set Hover State reports every grippable target as a latch hover, so this style is only reached if a subclass sets the pickup hover state itself. |
| var | LaserStyle_Hover_LatchLaser Style | Struct_Laser_Style_Item | Colour and end radii used while the beam is over an actor that offers a grip and nothing is held yet. Set Hover State chooses it for any grippable target, latch and pickup alike. |
| fn | SetLaserColorStyle | (LaserStyle: Struct_Laser_Style_Item split, DeltaTime: float) | Eases the beam towards the colour and the start and end radii of the given style, at the rate set by Laser Visual Interp Time. Does nothing while no beam actor exists, so it is safe to call with the laser switched off. |
| fn | getDesiredLaserStyleStyle | (out LaserStyle: Struct_Laser_Style_Item) | Returns the style the beam should be showing right now: the latch or pickup style while something is held, the pressed style while select is down, and otherwise the style for the current hover state. While the ability is hidden it returns a fixed transparent grey, which is what fades the beam away. |
| fn | SetHoverStateHover | (out AlternateLocation: bool, out Location: Vector) | Clears the hover state and works it out again from the current trace, ticking the highlight on the select or grip component it finds under the pointer. Reports back an alternate end point for the beam when a selectable overrides its hit location or when the grip offers an attach socket to snap to. |
| fn | HandleSelectSelect | () | Presses whatever the beam is pointing at. Over an interactive widget it passes the Source Info on and presses the left mouse button through the widget interaction; otherwise it asks each selectable interaction on the hit actor in turn and presses the first that accepts, playing the empty-click sound when none does. |
| event | InitiateControllerAbility | (Pawn: Pawn, MotionController: Actor, Side: E_Side) | Called by the motion controller once it has spawned this ability, handing over the owning pawn, controller actor and hand side. The laser adds nothing of its own here; extend it if you need setup at creation time. |
| event | IncreaseGrabbingSpeed | (Start: float, End: float) | Ramps the speed at which a held object chases its target transform from the start value to the end value over one second, on an ease-in-out curve. Used when a pickup snaps to the controller so it accelerates into the hand instead of jumping there. |
| event | SetLaser | (Set: bool) | Spawns the spline beam and expands it over half a second, or collapses it over the same time and lets it destroy itself when passed false. Called whenever the visible beam should come and go, such as while an object is snapped to the controller. |
| event | Server_Grip | (GripComponent: BPC_Interaction_Grip) | Runs on the server to record the gripped component in the replicated grab definition, which is what makes remote clients replay the grip. Sent only for components whose actor replicates. |
| event | GripActor | (HitLocation: Vector, GrabComponent: BPC_Interaction_Grip) | Takes hold of a grip component at the point the beam hit it. Releases anything already held on both sides, stores the grab definition, then sets the attach point up for the kind of grip: a pickup either snaps to the controller or stays out at its hit distance, while a latch spawns a latching helper, swaps the no-grab bindings for the snapped ones and takes focus of the controller. |
| event | Server_DesiredGrippedActorTransform | (Transform: Transform) | Runs on the server to store the transform this laser wants the held actor to have. Replicated to the other clients so the pickup coordinator can average it with the other abilities holding the same actor. |
| event | Server_Release | () | Runs on the server to clear the replicated grab definition, which drops the held actor on every remote client. |
| event | GrabbingActor_Release | () | Lets go of whatever the laser is holding: restores the no-grab bindings, gives up focus of the controller and clears the grab definition on client and server. Releasing a pickup also destroys the offset helper, and one that was snapped to the hand brings the beam and its end sphere back. Does nothing when nothing is held. |
| event | GrabbingActor_Grip | (GripComponent: BPC_Interaction_Grip) | Takes hold of the given grip component at its owner's location, as though the beam had hit it there. Call it to make the laser grab something without the player pointing at it. |
| event | GrabbingAbility_GripNewActorWithSameProperties | (GripComponent: BPC_Interaction_Grip) | Moves the laser's grip onto a different component without moving the attach point, so a swapped-in actor is held exactly where the old one was. Used when an object replaces itself while being carried. |
| event | ButtonForwardKey | (Key: E_Controller_Buttons, Set: bool) | Forwards a button press or release on this hand to the held component, which broadcasts it on its own button-forward delegate. Called by the laser's helper actor from the forwarded input actions, and only meaningful while something is gripped. |
| event | ButtonForwardThumbstick | (Axis: Vector2D) | Forwards this hand's thumbstick axes to the held component, so a carried object can read the stick directly. Only meaningful while something is gripped. |
| event | ButtonForwardTriggerAxis | (Value: float) | Forwards this hand's analogue trigger value to the held component, so a carried object can read a continuous squeeze rather than a press. |
Helper
BP_Helper_ControllerAbility_Laser4 members
| Kind | Name | Signature | Description |
|---|---|---|---|
| var | PointerIndexPointer | int | Pointer index this helper's widget interaction reports to the UI, so two hands pointing at the same widget are told apart. Taken from the game state's pointer index counter as the ability spawns the helper rather than set by hand. |
| var | ControllerAbilityLaser | BPC_ControllerAbility_Laser | The laser ability this helper carries the beam and widget interaction for. Set on spawn; every input action the helper receives is passed straight back to it, so a helper without one does nothing. |
| event | AutoTurnSelectedActor | () | Starts the short timeline that levels a remotely held object, easing the grab offset's pitch and roll away over 0.7 seconds and leaving its yaw as it is. Call it after a pickup so the object hangs upright on the beam. |
| event | SetVisible | (Set: bool) | Shows or hides the sphere and point light that mark the end of the beam. The beam itself is a separate spline actor, switched on and off with Set Laser on the ability. |