Skip to content

BehtomAdeli/VirtualLab-PDVH

Repository files navigation

Quest 3 Trial Manager – Unity Package

A Unity package for running video-based behavioral trials on Meta Quest 3, collecting high-frequency hand kinematics, head/camera pose, eye-gaze, and phone pose, detecting touch/click interactions, and sending BCI2000 event triggers, including online reach-onset detection (ReachInit) based on hand movement distance and thresholding.


Overview

This package implements a complete experimental pipeline:

  1. Welcome & instruction flow
  2. Ready period (baseline for movement)
  3. Stimulus trials (video or blank)
  4. Click / reach interaction window
  5. Rest periods
  6. End screen

During trials, the system logs per-frame tracking data to CSV and emits BCI2000 events aligned with trial structure, reach initiation, and touch responses.


Key Features

  • Deterministic trial playlist (seeded shuffle)
  • Video-based stimuli (U, I, S, B groups)
  • XR Hands joint tracking (left & right, full skeleton)
  • Eye-gaze via CenterEye (when available)
  • Phone-based touch detection
  • Online reach-onset detection (ReachInit)
  • BCI2000 integration with safe event pulsing
  • High-performance CSV logging (minimal allocations)

Requirements

Unity & XR

  • Unity with XR Plug-in Management enabled
  • XR Hands package installed and active
  • OpenXR (recommended for Quest 3)

Hardware

  • Meta Quest 3 with hand tracking enabled

Optional

  • BCI2000 with Unity integration (UnityBCI2000, BCI2000RemoteNET)

Scene Setup (Minimum)

Create an empty GameObject (e.g. TrialManager) and attach:

Script

  • PhoneScreenControllerQuest

Required References

  • headMount – XR head anchor transform
  • mainCamera – XR camera
  • tvVideoPlayerVideoPlayer for all videos
  • phone – phone target object
  • indexTipTransform – tracked index fingertip transform

UI / Optional

  • Phone screen text & background
  • Audio source + click sound
  • Room light (for instruction dimming)
  • BCI component (if used)

Trial Playlist Logic

Video Groups

Defined via:

videoGroups = "U,S,B" videosPerGroup = 10

Rules:

  • Videos are grouped by first character of filename
  • Example: U01.mp4 → group U
  • B = blank trials (no stimulus, no click required)

Shuffle

  • Controlled by shuffleSeed
  • Fully deterministic across runs

Timing Parameters

Parameter Description
welcomeTime Welcome video duration
instructionTime Instruction loop + light fade
readyTime Baseline period before trials
clickTimeWindow Max time to reach/click
restTime Mean rest duration
restRange Random variation (±)

Rest duration is clamped to 13–17 s.


Click Detection

A click is registered when:

  • isClickable == true
  • clicked == false
  • Distance between:
    • indexTipTransform.position
    • phone.transform.position
  • Is < 0.02 m

Effects:

  • UI feedback
  • CSV Click = 1
  • ClickTouch BCI event pulse

Reach Onset Detection (ReachInit)

Concept

ReachInit detects initial hand movement onset relative to a baseline (Ready period), using a distance-from-baseline formula and a user-defined threshold.

This runs online during the trial, independently of touch/click detection.

Logic (High Level)

  1. During Ready, compute baseline mean position: p0 = mean(indexTipPosition)

  2. During trial, compute distance: d(t) = || p(t) − p0 ||

  3. If: d(t) > reachThreshold

and ReachInit has not yet fired → trigger event.

Behavior

  • Fires once per trial
  • Logged to CSV
  • Emits BCI2000 ReachInit pulse
  • Can be configured to use:
  • Left or right index tip
  • Custom distance threshold

BCI2000 Integration

Defined Events

Event Purpose
TrialStart Trial onset
ReachInit Reach movement initiation
ClickTouch Phone touch
TrialRest Rest period

All events are 16-bit.

Event Timing

At Trial Start TrialStart = 1 ReachInit = 0 ClickTouch = 0 TrialRest = 0

On Reach Detection ClickTouch = 1

During Rest TrialStart = 0 TrialRest = 1

Safety

All pulses are sent via: SafeBCIPulse(eventName, value)

Which:

  • Guards against null BCI references
  • Prevents crashes if BCI is disconnected

CSV Logging

Output

  • One CSV per run
  • Timestamped filename:

TrackingData__yy-MM-dd-HH-mm-ss.csv

Logged Per Frame

  • Time (s)
  • Current video
  • Left & Right hand joints
  • Position, rotation
  • Velocity, acceleration
  • Head pose
  • Camera pose
  • Gaze origin & direction
  • Eye open amounts
  • Phone pose
  • Click flag
  • ReachInit flag

Performance Notes

  • Preallocated buffers
  • No per-frame allocations
  • Logging occurs in Update() via LogTrackingData()

Calibration

Phone Calibration

CalibrateOriginalPhonePosition()

  • Uses index tip + offset
  • Can auto-run on first click
  • Optionally moves phone immediately

Room Calibration

CalibrateRoomToHeadAndIndex()

  • Aligns chair/table/TV to head & hand
  • Requires optional scene references

Common Issues

No hand data

  • Ensure XR Hands is running
  • Confirm Quest hand tracking is enabled

ReachInit never fires

  • Check baseline period (Ready)
  • Increase reachThreshold
  • Verify correct index tip is selected

Clicks not detected

  • Adjust distance threshold
  • Verify phone and finger are in same coordinate space

CSV not written

  • Custom path may be invalid on Quest
  • Falls back to Application.persistentDataPath

Recommended Extensions

  • Velocity-based reach detection
  • Separate ReachInit for left/right hands
  • Buffered logging coroutine
  • Adaptive thresholds per participant

License

Add your lab or project license here.


Maintainer:
Your Name / Lab
Unity + Quest 3 Experimental Framework

About

C# Codes for running PDVH VRenv.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages