Develop

Distance Grabbing

Updated: Sep 4, 2026
Distance grabbing lets a ray manipulate an object that is outside direct reach. Add DistanceGrabbable to a transform entity after enabling the grabbing feature.

Add a distance grab

import {
  DistanceGrabbable,
  MovementMode,
  RayInteractable,
  World,
} from '@iwsdk/core';

const world = await World.create(container, {
  features: { grabbing: true },
});

const entity = world.createTransformEntity(mesh);
entity.addComponent(RayInteractable);
entity.addComponent(DistanceGrabbable, {
  movementMode: MovementMode.MoveTowardsTarget,
  moveSpeedFactor: 0.1,
  targetPositionOffset: [0, 0, -0.3],
  targetQuaternionOffset: [0, 0, 0, 1],
});
The target position offset is expressed in the input source’s local space. The quaternion offset is composed with the input source’s orientation.

Movement modes

MovementMode has four values:
ValueBehavior
MoveTowardsTarget
Interpolates position and orientation toward an offset from the input source.
MoveAtSource
Applies the input source’s position delta while preserving the object’s distance.
MoveFromTarget
Delegates movement to the standard projected-ray handle.
RotateAtSource
Rotates in place and disables translation and scale for the handle.

MoveTowardsTarget behavior

On each update, the handle:
  1. Rotates targetPositionOffset by the pointer orientation and adds it to the pointer origin.
  2. Multiplies the pointer quaternion by targetQuaternionOffset.
  3. Interpolates the object’s world position and quaternion toward those targets.
  4. Snaps to the target when the remaining distance is no more than 0.005 world units.
The interpolation factor is based on moveSpeedFactor, frame delta, and the handle’s internal scale. It is not a fixed distance per frame.
Set moveSpeedFactor in the initial addComponent() data, as shown in the first example. GrabSystem copies it into the handle when the component is initialized, so changing the component field later does not reconfigure the existing handle. The value defaults to 0.1 and uses a scale from 0 to 1.

Transform constraints

Enable or disable each transform channel and set per-axis limits.
entity.addComponent(DistanceGrabbable, {
  movementMode: MovementMode.MoveFromTarget,
  rotate: true,
  translate: true,
  scale: false,
  translateMin: [-2, 0, -2],
  translateMax: [2, 3, 2],
});
The default minimum values are negative infinity and the default maximum values are positive infinity.

Return to the starting transform

Set returnToOrigin to restore the position, orientation, and scale captured when each grab starts.
entity.addComponent(DistanceGrabbable, {
  movementMode: MovementMode.MoveAtSource,
  returnToOrigin: true,
});
The handle captures the origin transform at the start of each grab. Restoration occurs on the final handle update after release.

Detach while grabbed

detachOnGrab: true attaches the target to the scene or level root when grabbing begins. Use it when a parent transform must not continue to affect the manipulated object.