Skip to content

Class: GrabSystem

Defined in: packages/core/src/grab/grab-system.ts:61

Manages interactive object grabbing and manipulation for VR/AR experiences.

Remarks

  • Uses the @pmndrs/handle library for precise multitouch manipulation.
  • Automatically creates handle instances for entities with grabbable components.
  • Supports three types of grab interactions: one‑hand, two‑hand, and distance grabbing.
  • Automatically cleans up handle instances when grabbable components are removed.

Examples

ts
// Add to your world to enable grab interactions
world.addSystem(GrabSystem)

// Create a grabbable box
const box = world.createEntity()
box.addComponent(OneHandGrabbable, {})
ts
// Create an object that can be scaled with two hands
const sculpture = world.createEntity()
sculpture.addComponent(TwoHandsGrabbable, {
  scaleMin: [0.5, 0.5, 0.5],
  scaleMax: [3, 3, 3]
})

See

Extends

  • System<{ useHandPinchForGrab: { default: false; type: Boolean; }; }, { distanceGrabbables: { required: Component<{ detachOnGrab: { default: false; type: Boolean; }; movementMode: { default: string; enum: { MoveAtSource: string; MoveFromTarget: string; MoveTowardsTarget: string; RotateAtSource: string; }; type: Enum; }; moveSpeedFactor: { default: number; type: Float32; }; returnToOrigin: { default: false; type: Boolean; }; rotate: { default: true; type: Boolean; }; rotateMax: { default: [number, number, number]; type: Vec3; }; rotateMin: { default: [number, number, number]; type: Vec3; }; scale: { default: true; type: Boolean; }; scaleMax: { default: [number, number, number]; type: Vec3; }; scaleMin: { default: [number, number, number]; type: Vec3; }; targetPositionOffset: { default: [number, number, number]; type: Vec3; }; targetQuaternionOffset: { default: [number, number, number, number]; type: Vec4; }; translate: { default: true; type: Boolean; }; translateMax: { default: [number, number, number]; type: Vec3; }; translateMin: { default: [number, number, number]; type: Vec3; }; }>[]; }; handles: { required: Component<{ instance: { default: any; type: Object; }; }>[]; }; oneHandGrabbables: { required: Component<{ rotate: { default: true; type: Boolean; }; rotateMax: { default: [number, number, number]; type: Vec3; }; rotateMin: { default: [number, number, number]; type: Vec3; }; translate: { default: true; type: Boolean; }; translateMax: { default: [number, number, number]; type: Vec3; }; translateMin: { default: [number, number, number]; type: Vec3; }; }>[]; }; twoHandsGrabbables: { required: Component<{ rotate: { default: true; type: Boolean; }; rotateMax: { default: [number, number, number]; type: Vec3; }; rotateMin: { default: [number, number, number]; type: Vec3; }; scale: { default: true; type: Boolean; }; scaleMax: { default: [number, number, number]; type: Vec3; }; scaleMin: { default: [number, number, number]; type: Vec3; }; translate: { default: true; type: Boolean; }; translateMax: { default: [number, number, number]; type: Vec3; }; translateMin: { default: [number, number, number]; type: Vec3; }; }>[]; }; }, this>

Constructors

Constructor

new GrabSystem(_w, _qm, _p): GrabSystem

Defined in: node_modules/.pnpm/elics@3.4.2/node_modules/elics/lib/system.d.ts:76

Parameters

_w

World

_qm

QueryManager

_p

number

Returns

GrabSystem

Inherited from

createSystem( { oneHandGrabbables: { required: [OneHandGrabbable], }, twoHandsGrabbables: { required: [TwoHandsGrabbable], }, distanceGrabbables: { required: [DistanceGrabbable], }, handles: { required: [Handle], }, }, { /** * Controls whether hand pinch gestures are forwarded as squeeze events for grab interactions. * Set to `false` to disable pinch-to-grab and require the physical squeeze button instead. * @default false */ useHandPinchForGrab: { type: Types.Boolean, default: false }, }, ).constructor

Properties

camera

readonly camera: PerspectiveCamera

Defined in: packages/core/src/ecs/system.ts:63

Inherited from

System.camera


cleanupFuncs

readonly cleanupFuncs: () => void[]

Defined in: packages/core/src/ecs/system.ts:66

Returns

void

Inherited from

System.cleanupFuncs


config

config: SystemConfigSignals<S>

Defined in: packages/core/src/ecs/system.ts:49

Inherited from

System.config


createEntity()

createEntity: () => Entity

Defined in: packages/core/src/ecs/system.ts:81

Returns

Entity

Inherited from

System.createEntity


globals

globals: Record<string, any>

Defined in: packages/core/src/ecs/system.ts:54

Inherited from

System.globals


input

readonly input: InputManager

Defined in: packages/core/src/ecs/system.ts:61

Inherited from

System.input


isPaused

isPaused: boolean

Defined in: packages/core/src/ecs/system.ts:48

Inherited from

System.isPaused


player

readonly player: XROrigin

Defined in: packages/core/src/ecs/system.ts:58

Inherited from

System.player


playerEntity

readonly playerEntity: Entity

Defined in: packages/core/src/ecs/system.ts:59

Inherited from

System.playerEntity


playerHeadEntity

readonly playerHeadEntity: Entity

Defined in: packages/core/src/ecs/system.ts:60

Inherited from

System.playerHeadEntity


priority

priority: number

Defined in: packages/core/src/ecs/system.ts:53

Inherited from

System.priority


queries

queries: Record<keyof Q, Query>

Defined in: packages/core/src/ecs/system.ts:50

Inherited from

System.queries


queryManager

queryManager: QueryManager

Defined in: packages/core/src/ecs/system.ts:52

Inherited from

System.queryManager


renderer

readonly renderer: WebGLRenderer

Defined in: packages/core/src/ecs/system.ts:64

Inherited from

System.renderer


scene

readonly scene: Scene

Defined in: packages/core/src/ecs/system.ts:62

Inherited from

System.scene


visibilityState

readonly visibilityState: Signal<VisibilityState>

Defined in: packages/core/src/ecs/system.ts:65

Inherited from

System.visibilityState


world

world: World

Defined in: packages/core/src/ecs/system.ts:51

Inherited from

System.world


xrFrame

xrFrame: XRFrame

Defined in: packages/core/src/ecs/system.ts:56

Inherited from

System.xrFrame


xrManager

xrManager: WebXRManager

Defined in: packages/core/src/ecs/system.ts:55

Inherited from

System.xrManager

Methods

forceRelease()

forceRelease(entity): void

Defined in: packages/core/src/grab/grab-system.ts:198

Force-release entity if it is currently being held.

Parameters

entity

Entity

Returns

void

Remarks

Cancels every active pointer on the entity's grab handle, which causes update() on the next frame to remove the Grabbed tag. Safe to call when the entity is not held or has never been grabbable — a no-op in those cases.

Useful for game-state changes that need to drop held items: level resets, weapon swaps, death/respawn, cinematics, etc.

Example

ts
const grab = world.getSystem(GrabSystem);
grab.forceRelease(weaponEntity);

getHolderHand()

getHolderHand(entity): "left" | "right"

Defined in: packages/core/src/grab/grab-system.ts:228

Identify which controller is currently holding entity.

Parameters

entity

Entity

Returns

"left" | "right"

'left' or 'right' when a single hand holds the entity, null when the entity is not held (or has no grab handle).

Remarks

For two-handed grabs (both controllers active on the same entity), the left hand is reported. Callers needing per-hand state for two-handed interactions should track grab/release events themselves rather than polling this method.

Useful for hand-aware behaviors: recoil/animation that should react to the holding controller, hand-specific UI prompts, etc.

Example

ts
const grab = world.getSystem(GrabSystem);
const hand = grab.getHolderHand(gunEntity);
if (hand) {
  playRecoilOn(hand);
}

init()

init(): void

Defined in: packages/core/src/grab/grab-system.ts:85

Returns

void

Overrides

System.init


play()

play(): void

Defined in: packages/core/src/ecs/system.ts:79

Returns

void

Inherited from

System.play


stop()

stop(): void

Defined in: packages/core/src/ecs/system.ts:80

Returns

void

Inherited from

System.stop


update()

update(delta, time): void

Defined in: packages/core/src/grab/grab-system.ts:136

Per-frame tick. Both arguments are in seconds (Three.js Clock convention), not milliseconds.

Parameters

delta

number

Seconds since the previous frame.

time

number

Accumulated Clock.elapsedTime (seconds since the render loop started ticking the clock); monotonic across frames within a session.

Returns

void

Overrides

System.update

Privacy | Terms