Variables in scripts (CONDITION, PARTICIPANTS, COLLECTED_DATA)
What's available inside a Customized Action or Data Collector script — the three globals you'll read most.
These pages are not yet fully reviewed. The LUIDA team is continuing to review and improve them. If you find anything wrong on these pages, or have questions that aren't resolved by reading them, please ask or report to the LUIDA team.
LUIDA exposes three globals to scripts that run inside its automation system: CONDITION, PARTICIPANTS, and COLLECTED_DATA. They cover the three things you most often want to know inside an action or a data calculator: what conditions are active, who's playing, and what events have been logged so far.
CONDITION
A plain JavaScript object whose keys are your variable names and whose values are the active values for the current trial.
Available: only when the LUIDA experiment-progress automation feature is enabled and during a trial state (the trial loop, including Trial - Start, Trial - Rest, and any user-defined states between them).
Lookup: CONDITION["<variableName>"] — case-sensitive, exact match.
Examples:
// In a Customized Action on Stimulus state's "On State Start":
const target = CONDITION["responseTarget"]; // "color" or "meaning"
const fontColor = CONDITION["fontColor"]; // "red" or "blue"
const textMeaning = CONDITION["textMeaning"]; // "RED" or "BLUE"
const depth = CONDITION["depth"]; // "near" or "far" (between-subjects)
// Show the stimulus
SetText(textMeaning);
SetChildPosition("Stimulus", 0, depth === "near" ? 1.5 : 3.0, 0);
ShowItem();When values change:
- Within-subjects values swap at the boundary between
Trial - Restand the nextTrial - Start. SoOn State Startof Trial - Start sees the new values. - Between-subjects values are set once when the session starts and don't change for the duration.
Caveats:
- Outside of trial states (during
End, or before the firstTrial - Start),CONDITIONmay be empty or stale. Don't read it fromEndstate actions — use$.groupState.currentConditionfor the last-known values if you really need them post-trial. - If you misspell a variable name, the lookup returns
undefined. There's no compile-time check. - Type: values are always strings (the value strings from your variable definitions). If you need a number, parse with
Number(...)orparseInt(...).
PARTICIPANTS
An array of PlayerHandle objects, 1-indexed.
Available: in any state-listening action or data calculator script that runs after ParticipantManager has populated the array (i.e., after the session has started — basically always except very early init).
Lookup: PARTICIPANTS[<n>] where n is the 1-based participant index.
Examples:
// Send haptics to the first participant
const player = PARTICIPANTS[1];
if (player) {
player.send("haptics", { target: "right", frequency: 200, amplitude: 0.7, duration: 0.1 });
}
// Read the second participant's bone position (for paired studies)
const p2 = PARTICIPANTS[2];
if (p2) {
const headPos = p2.getHumanoidBonePosition(HumanoidBone.Head);
// ...do something with headPos
}Caveats:
- 1-indexed, not 0-indexed.
PARTICIPANTS[0]isundefined. This is a deliberate ergonomic choice (matches LUIDA'spIDwhich is also 1-based) but bites JavaScript-trained programmers. - For sessions with
pNum=1, onlyPARTICIPANTS[1]is defined. For multi-participant sessions,PARTICIPANTS[1],PARTICIPANTS[2], etc., are all defined. - A participant disconnecting mid-session does not shift others' indices —
PARTICIPANTS[2]becomesundefined(or returns a stale handle that throws on use). Always guard withif (PARTICIPANTS[n]). - The full set of methods on
PlayerHandleis inAssets/Doc/CCK-Types.d.tsunderPlayerHandle.
COLLECTED_DATA
A plain JavaScript object that accumulates SendDataToCollector(label, value) calls between ProcessAndSaveCollectedData invocations.
Available: in your data calculator script (Assets/_Experiment_/Scripts/CustomDataCollection/<scene>_DataCollector.js), as the input to calculateData(). Not directly accessible from arbitrary state-listening actions — use SendDataToCollector to write, not direct manipulation.
Lookup: COLLECTED_DATA["<label>"] — case-sensitive.
Examples:
// Customized action on Stimulus state's "On State Start":
SendDataToCollector("stimulusOnsetMs", Date.now());
// Customized action on Response state's "On State Exit":
SendDataToCollector("responseMs", Date.now());
SendDataToCollector("correct", responseMatchesTarget);
ProcessAndSaveCollectedData();
// Inside the data calculator script:
function calculateData() {
return {
sID: $.groupState.sessionID,
trial: $.getStateCompat("global", "exp_trialID", "integer"),
rt_ms: COLLECTED_DATA["responseMs"] - COLLECTED_DATA["stimulusOnsetMs"],
correct: COLLECTED_DATA["correct"],
fontColor: CONDITION["fontColor"],
textMeaning: CONDITION["textMeaning"],
};
}Lifecycle:
- Calls to
SendDataToCollector(label, value)accumulate values in$.groupState.collectedData, which is whatCOLLECTED_DATAaliases. ProcessAndSaveCollectedDatareads the current state ofCOLLECTED_DATA, calls yourcalculateData(), and appends the returned object to the upload queue.COLLECTED_DATAdoes NOT reset betweenProcessAndSaveCollectedDatacalls. Values you wrote in a previous trial are still there when the next trial starts. If you want a clean slate per trial, write fresh values for every key, or explicitly set obsolete ones toundefined.
Caveats:
- Don't put huge values in
COLLECTED_DATA. The Console's payload-size batching keeps records under 100 KB UTF-8 per upload, but a single record over the limit will cause that record to fail. - Don't put functions or non-JSON-serializable values. The record gets
JSON.stringify'd before upload. - The keys you use here are independent of the column names in your final data export —
calculateData()defines the export shape.
See also
- Concepts → Within vs between subjects — where
CONDITIONvalues come from. - Concepts → Conditions, sessions, participants — when
PARTICIPANTSis populated. - Concepts → Data collection — the lifecycle of
COLLECTED_DATAend-to-end. Assets/Doc/LUIDA-DataCollectorScriptDoc.md— the source-of-truth markdown this page is based on.Assets/Doc/CCK-Types.d.ts— full ClusterScript API includingPlayerHandle.