---
title: AFS_UX_Laser
product: Advanced Framework Pro
version: 1.0
engine: Unreal Engine 5.8
updated: 2026-10-05
canonical: https://docs.human-codeable.com/plugins/afs-ux-laser.html
---

System

# 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

#### Requires

None

#### Required by

None

2 assets34 API members

## 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

1. Enable `AFS_UX_Laser`.
2. Add `BPC_ControllerAbility_Laser` to the motion controller Blueprint.
3. 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.

[![The laser resting on a world-space widget](../images/AFS_UX_Laser_result-1600.webp?v=669beed2)](../images/AFS_UX_Laser_result-1600.webp?v=669beed2)

The laser resting on a world-space widget

## 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_Laser**31 members

extends `BPC_ControllerAbility` · implements `Interface_GrabbingActor`

Hand ability giving one motion controller a pointing laser: hovering, selecting, gripping at a distance and driving UMG widgets all run through it. Add it to a motion controller and it spawns the laser helper with the beam, the physics handle and the widget interaction, choosing a laser style per hover state. Pointer Transform Interaction decides what the thumbstick does to a remotely grabbed actor.

| Kind | Name | Signature | Description |
|---|---|---|---|
| var | `Pointer Transform Interaction`Settings | `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 | `Max Grab Distance Offset`Settings | `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 | `Laser Visual Interp Time`Settings | `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 | `Max Interpolation Distance`Settings | `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 | `Interpolation Speed`Settings | `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 | `Max Laser Length`Settings | `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 Default`Input | `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 Grab`Input | `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 | `Mapping Context Grip Snapped`Input | `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 | `Mapping Context Grab Remote`Input | `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 | `Laser Style Latch`Laser 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 | `Laser Style Pickup`Laser 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 | `Laser Style Select Pressed`Laser 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 | `Laser Style Default`Laser 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 | `Laser Style Hover Select`Laser 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 | `Laser Style Hover Pickup`Laser 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 | `Laser Style Hover Latch`Laser 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 | `HandleSelect`Select | `()` | 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. |
| fn | `SetHoverState`Hover | `(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 | `getDesiredLaserStyle`Style | `(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 | `SetLaserColor`Style | `(LaserStyle: Struct_Laser_Style_Item, 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. |
| 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. |
| 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. |

### Helper

**BP_Helper_ControllerAbility_Laser**3 members

extends `BP_Helper_ControllerAbility`

World-side actor for the laser ability, spawned with it: the beam start and end points, the sphere at the tip, the point light, the physics handle used for remote grabbing, the widget interaction and the attach points a snapped object hangs from. It also carries the laser's own input bindings. Spawned for you rather than placed; edit it to change what the laser looks like.

| Kind | Name | Signature | Description |
|---|---|---|---|
| var | `Controller Ability Laser` | `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. |
