XR Integration¶
Octoputs ships with a small Octoputs.XR module that bridges Unity's XR Interaction Toolkit into the standard Detector and Event pipelines. Your existing drag-and-drop setups work in VR by swapping the input layer — the slot logic, filters, conditions, layouts, and transforms stay exactly the same.
The XR module follows Unity's "optional dependency" pattern: the assembly definition gates everything on com.unity.xr.interaction.toolkit being installed. Non-VR users see no behavior change and no compile cost.
Install XR Interaction Toolkit¶
- Open Window → Package Manager.
- Click
+→ Add package by name and add: com.unity.xr.interaction.toolkit(3.0.0 or newer; older versions leave the XR module switched off)com.unity.xr.openxr(for cross-vendor headset support — Quest, Index, Pico, Vive)com.unity.xr.management(auto-installed as a dependency)- Open Edit → Project Settings → XR Plug-in Management and enable OpenXR for the platforms you target.
- In OpenXR settings, add the Interaction Profiles you need (Oculus Touch, Valve Index, Khronos Simple, etc.).
Once XRI is installed, the Octoputs.XR module's version-define activates and three new entries appear in the picker:
| Picker location | Type | Use |
|---|---|---|
| Detection → XR / XR Interactor | XRInteractorDetectionStrategy |
Mirror an XR interactor's hovered or selected objects into a Detector |
| Events → XR / XR Interactor Select | XRInteractorSelectEvent |
Fire on grip press or release (the XRI "select" edge) |
| Events → XR / XR Interactor Activate | XRInteractorActivateEvent |
Fire on trigger press or release (the XRI "activate" edge) |
Wire your scene¶
You can convert any mouse-driven Octoputs scene to VR with a handful of component swaps. (The VR Drag And Drop example takes another route: its hands find objects by touch and by a ray from the controller, and read the grip button directly, so they need none of the XR entries above. See Example: VR Drag And Drop.) Below assumes you've already followed Quick Start and have a working CursorAgent.
1. Replace the mouse cursor with an XR rig¶
Use the standard XRI setup: GameObject → XR → XR Origin (XR Rig). Configure one of the rig's hand GameObjects (typically LeftHand Controller or RightHand Controller) with an XRRayInteractor (for distance grabs) or an XRDirectInteractor (for direct/proximity grabs). XRI provides both presets out of the box.
2. Point the Detector at the XR interactor¶
On your existing CursorAgent → Detector:
- Detection Strategy — swap Raycast Detection Strategy for XR Interactor
- Interactor — drag in the controller hand's
XRRayInteractor(orXRDirectInteractor) - Signal — pick Hovered for a continuous "what's under the ray" feed, or Selected if you want the Detector to only see objects XRI has actively grabbed
The Detector's selection step still applies, including Is Attachable and any tag/layer filters you've added.
The ray only hovers objects the toolkit knows about, so add an XR Simple Interactable to every object you want to grab. Octoputs objects use trigger colliders: set the ray interactor's Raycast Trigger Interaction to Collide, or it looks straight through them.
- Detection Strategy: Detection → XR → XR Interactor.
- Interactor: the controller's ray interactor.
- Signal: Hovered, so whatever the ray points at is detected.
3. Drive the AttachingAgent from the controller¶
On your existing CursorAgent → Attaching Agent:
- Grab Event — swap Mouse Button Event for XR Interactor Select (Entered edge)
- Interactor — drag in the same
XRRayInteractoryou wired into the Detector - Drop Event — wire a second XR Interactor Select on the Exited edge, so letting go of grip drops. The select only starts while the ray is over an interactable, so an empty Drop Event (grab and drop on the same press) would need the ray back on an interactable to drop.
- Grab Event: XR Interactor Select on the Entered edge.
- Drop Event: a second XR Interactor Select on the Exited edge.
4. Carry along the controller ray¶
The mouse Drag Hand carries the held object along a ray from the camera through the cursor. On Drag Hand Target → Follow Ray Hit → Raycaster, and the same on Drag Hand Probe, swap Ray From Camera for Ray From Origin And Direction: origin is the controller's Object World Position, direction is the controller's Object Axis (Forward). Skip this and the held object follows the mouse, not your hand, and slots are picked under the mouse too.
That's it. Press Play with the headset connected. Aiming the controller ray at any AttachableObject highlights it (via the Detector's filter pass); pressing grip attaches it to the HoldPoint; releasing drops onto the configured destination point.
Example: VR Drag And Drop¶
Install the VR Drag And Drop example from the Jungle Hub. It brings the XR Interaction Toolkit and OpenXR with it; Octoputs itself never depends on them. The scene is a small sushi bar with an XR Origin, a Left VR Drag Hand and a Right VR Drag Hand. Hold grip to grab what your hand touches, or point at a sushi or plate up to 3 m away and grip to pull it in; let go to drop or throw. The chef serves three sushi onto the counter. Put one on a clean plate and set the plate on the serve belt: a trap door eats the sushi and the return belt brings the plate back dirty. Drop it in the sink and it is clean again two seconds later. Once the counter is empty, the chef serves a new round. Every piece is a stock Octoputs or Jungle component, and the scene's notes explain each one. The hand prefabs' notes list what changed from the mouse Drag Hand.
The scene also carries a Start XR component (Add Component → Octoputs → XR → Start XR). It starts the headset when the scene opens and stops it when the scene closes, so only the scenes that carry it run in VR and you can leave Initialize XR on Startup off in XR Plug-in Management. If the headset is already running, it leaves it alone.
No headset? Import the toolkit's XR Device Simulator sample (Package Manager → XR Interaction Toolkit → Samples) and drop its prefab in the scene to drive the hands with mouse and keyboard.
Recipe: Hands instead of controllers¶
XRI's hand-tracking interactors derive from the same XRBaseInteractor, so the wiring is identical — drop a hand-tracking XRPokeInteractor or XRDirectInteractor in place of the controller and reuse the same Detector and Event configurations. The pinch gesture maps to selectEntered/selectExited automatically through XRI's input action layer.
Recipe: Keep XRI's native grab, layer Octoputs on top¶
If you want XRI to handle the physical grab gesture (visual hand bones following the object, native release physics) and use Octoputs only for slot logic, point the Detector at the interactor in Selected mode. The Detector then reports objects only after XRI has already grabbed them. Wire an AttachmentPoint with the appropriate filters as the drop destination — Octoputs will snap the XRI-held object into the slot when conditions match.
This setup keeps Octoputs' value-add (filters, conditions, layout, stats, transfer commands) without competing with XRI's grab handling.
Module structure¶
| File | Purpose |
|---|---|
Assets/Plugins/Jungle/Octoputs - 3D Drag And Drop/Runtime/XR/Octoputs.XR.asmdef |
Assembly definition with the UNITY_XR_INTERACTION_TOOLKIT version-define |
XRInteractorDetectionStrategy.cs |
IDetectionStrategy mirroring XRI hover/select set into a Detector |
XRInteractorSelectEvent.cs |
IEvent on the XRI select edge (grip / pinch) |
XRInteractorActivateEvent.cs |
IEvent on the interactor's activate button (trigger), pressed or released |
Every type is wrapped in #if UNITY_XR_INTERACTION_TOOLKIT so the module compiles to zero bytes when XRI isn't present.
Troubleshooting¶
The XR entries don't appear in the picker.
: Check Window → Package Manager that com.unity.xr.interaction.toolkit is installed. The version-define on Octoputs.XR.asmdef only activates when the package is present. After installing, force a recompile via Assets → Reimport All if needed.
Octoputs.XR.asmdef shows a missing reference warning.
: The asmdef references Unity.XR.Interaction.Toolkit. Until you install XRI, that reference is unresolved — the warning is expected and harmless (the code inside is elided by the version-define).
XR Interactor Activate logs "does not read controller input".
: The activate button only exists on interactors that read controller input. The standard XRRayInteractor and XRDirectInteractor do; a poke or socket interactor does not. Use XRInteractorSelectEvent instead, which works with any XRBaseInteractor.
The ray passes over an object and nothing happens. : The object needs an XR Simple Interactable, and the ray interactor's Raycast Trigger Interaction must be Collide when the object only has trigger colliders.
Next steps¶
- Build a working drag-and-drop without XR first: Quick Start and Your First Drag and Drop. The XR layer plugs into a working scene rather than replacing it.
- Filter by tags and conditions: Tag-Based Filtering.
- Customize movement (springs, snap, ease): Transform Operations.