Skip to content

Reaction Time Tasks

Overview

This documentation covers four example scripts designed for reaction time and interaction experiments in virtual reality using the SightLab VR platform. These scripts demonstrate different ways to configure tasks, environments, and participant interactions.

1. Basic Reaction Time Task (reactionTime.py)

Purpose

To measure how long it takes participants to find a red sphere with their eyes and look at it.

Script Breakdown

  1. Setup Environment:
  2. Loads the dojo environment and a red sphere, which stays hidden until its turn.
  3. Reaction Time Measurement:
  4. The sphere appears at each of the four positions in turn, after a random wait of 1.5 to 2.5 seconds.
  5. A look counts once it has stayed on the sphere for the dwell time (0.5 seconds by default), so a glance that passes over it does not. The reaction time runs from the sphere's appearance to the start of the look that counted.
  6. The time is shown on screen and written to the trial data's Reaction Time column, and the sphere fades out. If it is not looked at, it fades out after 3 seconds and no time is recorded.
  7. The sphere is hidden between appearances, so gaze can't land on it then, and each appearance records at most one time.
  8. All four positions run in one SightLab trial.

Customization

  • Modify positions to change where the sphere appears, and in what order.
  • FADE_IN_SPHERE is the time, in seconds, the sphere takes to fade out.
  • Modify environment and target object.

2. Reaction Time with Selector Tool (reactionTime_Selector_Tool.py)

Purpose

Measures how quickly a participant points at a red ball and clicks it once it appears, using SightLab's selector (highlighter) tool.

Script Breakdown

  1. Setup:
  2. Loads the dojo environment and the red ball (Resources/objects/red_ball.osgb), and turns on the selector tool for the ball only. Nothing is highlighted when the pointer is on the ball, so the press is the only response.
  3. Draws the order of the positions and the waits from one random seed (see Repeating a session).
  4. Interaction Flow:
  5. The instructions ask the participant to click the ball as quickly as possible. The trigger (or left mouse button) continues.
  6. Each ball is its own SightLab trial, labelled Position 1 to Position 4. Every block of four trials shows each position once, in a random order.
  7. Each trial starts with a random wait of 1 to 3 seconds, then the ball appears at that trial's position.
  8. The participant points at the ball and presses the trigger. In a headset, each controller has a ray, and a press counts only for the controller whose ray is on the ball. On Desktop, the pointer comes from the hand at the lower right of the view and points where you look: turn the view with the mouse to aim, then left-click.
  9. The reaction time runs from the moment the ball is first drawn to the press. The trial then ends and the next one begins.
  10. If the participant cannot find the ball, the operator can press Space to skip it; that trial's reaction time is left blank.
  11. "Done. Thank you!" shows after the last trial.

Data Recorded

Each trial's row for ENTIRE_SCENE in the experiment summary has these columns:

Column What it records
Reaction Time Seconds from the ball appearing to the press that selected it. Blank for a skipped ball.
Position Which of the four positions (1 to 4)
Ball Position That position's coordinates
Foreperiod (secs) The random wait before the ball appeared
Misses Presses while the ball was showing that were not on it
Anticipations Presses before the ball appeared
Random Seed The seed that drew the session's order and waits

The trial data also flags each moment: ball shown, miss, anticipation, and the reaction time on the frame of the hit. The ball is a gaze object (sphere), so the usual dwell and fixation measures cover it. The ball is hidden between trials, so gaze can't land on it then, and Session Replay shows it only while it was visible.

Customization

Setting Default What it does
POSITIONS Four positions Where the ball appears, in meters. The ball's origin is at its base, so each position is where the ball rests; its center is 0.2 m higher.
NUM_TRIALS 4 Number of balls. Each block of len(POSITIONS) trials shows every position once.
FOREPERIOD_RANGE (1.0, 3.0) The random wait before each ball, in seconds
RANDOM_SEED None None draws a new seed every session; a number repeats a session (see below)
INSTRUCTIONS, END_TEXT The text before the first trial and after the last
SKIP_KEY ' ' (Space) The operator's key for skipping a ball

Repeating a session

The script prints the random seed at the start of each session and saves it in the experiment summary's Random Seed column. To run the same order of positions and the same waits again, set RANDOM_SEED to that number.

3. Shoot/Don't Shoot Task (reactionTime_Shoot_Dont_Shoot.py)

Purpose

Tests decision-making under time pressure by requiring participants to "shoot" threat objects while ignoring neutral objects.

Script Breakdown

  1. Object Classification:
  2. Four objects: two threats (a red and a green box) and two neutrals (a white and a blue sphere). Each is a gaze object with its own name: threat_red, threat_green, neutral_white, neutral_blue.
  3. Four possible spawn positions. All objects stay hidden until their trial.
  4. Task Logic:
  5. An instruction image (shoot_dont_shoot.jpg) explains the task; the trigger starts it.
  6. Each of the SET_TRIAL_COUNT trials shows one object, drawn at random, at a random position.
  7. The participant shoots by pointing at the object and pressing the trigger (Desktop: left-click), or holds fire. In a headset, a press counts only for the controller whose ray is on the object.
  8. The trial ends at the shot, or after TRIAL_LENGTH seconds without one.
  9. Shooting a threat or holding fire on a neutral object is correct.

Data Recorded

Each trial's row for ENTIRE_SCENE in the experiment summary has these columns:

Column What it records
Reaction Time Seconds from the object appearing to the shot. Blank when the participant held fire.
Object Category threat or neutral
UserShot? True if the participant shot, False if they held fire
Correct? True for a shot threat or a neutral left alone

Every trial has a category, a shot, and a correctness value, including trials where the participant held fire. Objects are hidden between trials, so gaze can't land on them then, and Session Replay shows each object only while it was visible.

Customization

  • Modify SET_TRIAL_COUNT to change the number of trials, and TRIAL_LENGTH for how long each object stays up (1.5 seconds by default).
  • Update object_list to add or replace objects, with a matching name for each in object_names. Each name must be unique: SightLab keeps one object per name for gaze data and replay.
  • Modify positions, the environment, and the objects.

4. Shoot/Don't Shoot in a Maze (reactionTime_Shoot_Dont_Shoot_maze.py)

Purpose

Adds complexity to the shoot/don't-shoot task by embedding it in a maze environment with proximity sensors.

Script Breakdown

  1. Environment Setup:
  2. Loads a maze model (Resources/environment/maze.osgb; can be swapped with your own).
  3. Places proximity sensors on the maze's proximity_geode1 and proximity_geode2 areas.
  4. Task Logic:
  5. Similar to the shoot/don't-shoot task but requires navigation. The same four objects are used, with the same names.
  6. Each trial's object stays hidden until the participant walks into a proximity area. It then appears about 2.5 m in front of them, at 1.5 m height and up to 1.5 m to either side, once per trial: walking into an area again does not move it.
  7. The participant shoots by pointing at the object and pressing the trigger (Desktop: left-click), or holds fire. The trial ends at the shot, or TRIAL_LENGTH seconds after it started.
  8. The reaction time runs from the moment the object appears, not from the start of the trial, so the time spent walking to the area is not included.

Data Recorded

The experiment summary has the same columns as the Shoot/Don't Shoot task (Reaction Time, Object Category, UserShot?, Correct?). If the participant never reached a proximity area, the object never appeared, so UserShot? and Correct? are left blank for that trial.

Customization

  • Adjust TRIAL_LENGTH for how long each trial lasts, including the walk to a proximity area (180 seconds by default).
  • Use proximityAreaPlacer to configure sensor areas.
  • As in the Shoot/Don't Shoot task, give each object in object_list a unique name in object_names.