Skip to main content

Interaction System

QWR SDK provides a powerful physics-based interaction system that allows users to grab, manipulate, and interact with objects in your XR application. This page explains how to use and customize the interaction system.

Interaction System Overview

The interaction system in QWR SDK includes:

  • Physics-based grabbing and manipulation
  • Distance grabbing with ray interaction
  • Object snapping and placement
  • Two-handed interactions
  • Custom interaction behaviors
  • Integration with Unity's physics system

Core Components

QWRInteractionManager

The QWRInteractionManager is the central component that coordinates all interactions between hands/controllers and objects in the scene.

// Access the interaction manager
QWRInteractionManager interactionManager = QWRInteractionManager.Instance;

// Register interactable objects
interactionManager.RegisterInteractable(myInteractable);

// Query interactions
bool isInteracting = interactionManager.IsInteracting(HandType.Right);
QWRInteractable currentObject = interactionManager.GetInteractedObject(HandType.Left);

QWRInteractor

The QWRInteractor component represents an entity that can interact with objects (like hands or controllers).

// Get interactors
QWRInteractor leftHandInteractor = QWRHandController.LeftHand.GetComponent<QWRInteractor>();
QWRInteractor rightHandInteractor = QWRHandController.RightHand.GetComponent<QWRInteractor>();

// Check if interactor is grabbing
bool isGrabbing = leftHandInteractor.IsGrabbing;

// Get currently grabbed object
QWRInteractable grabbedObject = leftHandInteractor.CurrentInteractable;

// Subscribe to interaction events
leftHandInteractor.OnGrabBegin += HandleGrabBegin;
leftHandInteractor.OnGrabEnd += HandleGrabEnd;

QWRInteractable

The QWRInteractable component makes an object interactable with hands and controllers.

// Create an interactable object
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
Rigidbody rb = cube.AddComponent<Rigidbody>();
QWRInteractable interactable = cube.AddComponent<QWRInteractable>();

// Configure interactable properties
interactable.grabType = GrabType.Both; // Can be grabbed by hands or controllers
interactable.twoHandedGrabEnabled = true; // Enable two-handed grabbing
interactable.throwVelocityMultiplier = 1.5f; // Increase throw velocity

// Subscribe to events
interactable.OnGrabbed += HandleObjectGrabbed;
interactable.OnReleased += HandleObjectReleased;

Making Objects Interactable

Basic Setup

To make an object interactable:

  1. Add a Rigidbody component to your object
  2. Add the QWRInteractable component
  3. Configure the interaction settings
// Example: Setting up an interactable object
public GameObject CreateInteractableObject(Vector3 position)
{
// Create a cube
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.position = position;

// Add rigidbody
Rigidbody rb = cube.AddComponent<Rigidbody>();
rb.mass = 1.0f;

// Add interactable component
QWRInteractable interactable = cube.AddComponent<QWRInteractable>();

// Configure interactable properties
interactable.grabType = GrabType.Both;
interactable.snapToHand = true;

return cube;
}

Grab Types

The QWRInteractable component supports different grab types:

  • GrabType.Hand: Can only be grabbed by hands
  • GrabType.Controller: Can only be grabbed by controllers
  • GrabType.Both: Can be grabbed by both hands and controllers
  • GrabType.None: Cannot be grabbed (but can still be touched)

Grab Points

You can define specific grab points on an object:

  1. Create empty GameObjects as children of your interactable object
  2. Position them where you want the hand/controller to grab
  3. Add the QWRGrabPoint component to each grab point
  4. Configure the grab point settings
// Example: Adding grab points programmatically
public void AddGrabPoints(QWRInteractable interactable)
{
// Create a grab point for the left hand
GameObject leftGrabPoint = new GameObject("LeftGrabPoint");
leftGrabPoint.transform.SetParent(interactable.transform);
leftGrabPoint.transform.localPosition = new Vector3(-0.1f, 0, 0);

QWRGrabPoint leftPoint = leftGrabPoint.AddComponent<QWRGrabPoint>();
leftPoint.handType = HandType.Left;
leftPoint.handPose = HandPose.Grab;

// Create a grab point for the right hand
GameObject rightGrabPoint = new GameObject("RightGrabPoint");
rightGrabPoint.transform.SetParent(interactable.transform);
rightGrabPoint.transform.localPosition = new Vector3(0.1f, 0, 0);

QWRGrabPoint rightPoint = rightGrabPoint.AddComponent<QWRGrabPoint>();
rightPoint.handType = HandType.Right;
rightPoint.handPose = HandPose.Grab;
}

Interaction Types

Direct Grabbing

Direct grabbing occurs when a hand or controller directly touches an interactable object.

// Configure direct grab settings
interactable.directGrabEnabled = true;
interactable.grabPriority = 10; // Higher priority objects are grabbed first

Ray Grabbing

Ray grabbing allows users to grab objects from a distance using a ray.

// Configure ray grab settings
interactable.rayGrabEnabled = true;
interactable.maxRayGrabDistance = 5.0f;
interactable.rayGrabOffset = new Vector3(0, 0, -0.2f);

Two-Handed Grabbing

Two-handed grabbing allows users to manipulate objects with both hands simultaneously.

// Configure two-handed grab settings
interactable.twoHandedGrabEnabled = true;
interactable.rotationMode = TwoHandedRotationMode.First; // First hand controls rotation
interactable.scaleEnabled = true; // Allow scaling with two hands
interactable.minScale = 0.5f;
interactable.maxScale = 2.0f;

Physics Interactions

Physics Grab Modes

The QWRInteractable component supports different physics grab modes:

  • PhysicsGrabMode.Kinematic: Object becomes kinematic when grabbed (default)
  • PhysicsGrabMode.Velocity: Uses velocity to move the object (more physics-based)
  • PhysicsGrabMode.Joint: Uses a configurable joint (most realistic)
// Configure physics grab mode
interactable.physicsGrabMode = PhysicsGrabMode.Joint;

// Configure joint settings (for Joint mode)
interactable.jointDamping = 10f;
interactable.jointSpring = 100f;

Throwing Objects

When releasing objects, velocity is applied to simulate throwing:

// Configure throwing behavior
interactable.throwVelocityMultiplier = 1.5f; // Increase throw velocity
interactable.throwAngularVelocityMultiplier = 1.0f; // Normal angular velocity

Advanced Interaction Features

Snapping and Placement

Objects can snap to predefined positions or surfaces:

// Configure snapping behavior
interactable.snapToSurface = true;
interactable.snapRotation = true;
interactable.snapDistance = 0.1f;

Custom Hand Poses

You can define custom hand poses for specific objects:

  1. Create a QWRHandPoseDefinition scriptable object
  2. Configure the finger positions and rotations
  3. Assign it to the QWRGrabPoint component
// Assign a custom hand pose
QWRGrabPoint grabPoint = GetComponent<QWRGrabPoint>();
grabPoint.customPose = myCustomPose;

Interaction Constraints

You can constrain how objects can be moved and rotated:

// Configure movement constraints
interactable.constrainMovement = true;
interactable.movementConstraints = new Vector3(1, 0, 1); // Only move on X and Z axes

// Configure rotation constraints
interactable.constrainRotation = true;
interactable.rotationConstraints = new Vector3(0, 1, 0); // Only rotate around Y axis

Custom Interaction Behaviors

Creating Custom Interactables

You can create custom interactable behaviors by inheriting from QWRInteractable:

public class CustomInteractable : QWRInteractable
{
// Override grab behavior
protected override void OnGrab(QWRInteractor interactor)
{
base.OnGrab(interactor);
// Custom grab behavior
Debug.Log("Custom grab behavior");
}

// Override release behavior
protected override void OnRelease(QWRInteractor interactor)
{
base.OnRelease(interactor);
// Custom release behavior
Debug.Log("Custom release behavior");
}
}

Creating Custom Interactors

You can create custom interactor behaviors by inheriting from QWRInteractor:

public class CustomInteractor : QWRInteractor
{
// Override hover behavior
protected override void OnHoverEnter(QWRInteractable interactable)
{
base.OnHoverEnter(interactable);
// Custom hover behavior
Debug.Log("Custom hover behavior");
}

// Override grab detection
protected override bool ShouldGrab()
{
// Custom grab detection logic
return base.ShouldGrab() && CustomCondition();
}

private bool CustomCondition()
{
// Your custom condition
return true;
}
}

UI Interaction

The interaction system integrates with Unity's UI system for XR interfaces.

UI Interaction Components

  • QWRUIInteractor: Allows hands/controllers to interact with UI elements
  • QWRUICanvas: Makes a Canvas interactable in XR
// Configure UI interaction
QWRUIInteractor uiInteractor = GetComponent<QWRUIInteractor>();
uiInteractor.uiLayerMask = LayerMask.GetMask("UI");
uiInteractor.pointerTriggerType = PointerTriggerType.ButtonPress;

Performance Considerations

Interactions can be performance-intensive. Here are some optimization tips:

  • Use simpler colliders for interaction detection
  • Adjust physics update rates based on your target platform
  • Use the PhysicsGrabMode.Kinematic for better performance
  • Limit the number of simultaneously interactable objects

Troubleshooting

Objects Not Grabbable

If objects can't be grabbed:

  • Ensure the object has a Rigidbody component
  • Check that the QWRInteractable component is properly configured
  • Verify that the object's layer is included in the interaction layer mask
  • Check for collider issues (missing collider or trigger collider)

Physics Issues

If you experience physics issues:

  • Adjust the physics grab mode to suit your needs
  • Check for collider overlaps or interpenetration
  • Adjust Unity's physics settings (solver iterations, etc.)
  • Consider using a different physics grab mode

Two-Handed Interaction Problems

If two-handed interactions aren't working correctly:

  • Ensure twoHandedGrabEnabled is set to true
  • Check that both hands can reach the object simultaneously
  • Verify that the rotation and scaling modes are configured correctly

Next Steps

Now that you understand the interaction system, you can explore: