Signals & state keys
The inter-object protocol that LUIDA uses to wire scenes, items, and global state together.
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's runtime uses CCK signals and state keys to coordinate between scripts, items, and gimmicks. This page is one big table you'll Cmd-F. This is admin-level reference material — most experiment authors never need it because LUIDA's CCK components, state-listening actions, and customized actions wrap these primitives.
Global state keys
These are read/written via $.setStateCompat("global", <key>, <type>, <value>) and $.getStateCompat("global", <key>, <type>).
| Key | Type | Set by | Read by | Meaning |
|---|---|---|---|---|
state_currentID | integer | StateMachine prefab on transition | All state-listening items | Active state index (0-based) |
exp_trialID | integer | ConditionManager.js at trial-rest-to-start boundary | ConditionManager, data calculator scripts | Current trial number (0-based) |
state_enter | boolean | StateMachine on transition | StateListeningItemBase.js | Pulse to fire on-enter actions |
state_exit | boolean | StateMachine on transition | StateListeningItemBase.js | Pulse to fire on-exit actions |
exp_showItem | boolean | "Show item" / "Hide item" actions | CCK Show/Hide gimmicks attached to the item | Visibility toggle for state-listening items |
exp_recordCustomData | boolean | "Process and Save" action | CustomDataUploader.js | Pulse to snapshot a record |
exp_uploadCustomData | boolean | "Upload" action | CustomDataUploader.js | Pulse to flush queue |
luida_avatar_cmd | integer | LuidaAssignAvatarGimmick | AvatarManager.js polling | > 0 = assign avatar at index N-1; -1 = unassign; 0 = no-op |
luida_avatar_participant | integer | LuidaAssignAvatarGimmick | AvatarManager.js polling | Target participant (1-based) for current avatar command |
someCckState (and other arbitrary keys) | various | Researcher-defined CCK gimmicks | Custom data calculator via getStateCompat | Researcher-defined state for experiment-specific logic |
Item state keys
These are read/written via $.setStateCompat("this", <key>, <type>, <value>) (or with an item reference for cross-item).
| Key | Type | Set by | Read by | Meaning |
|---|---|---|---|---|
qID | integer | LuidaQuestionnaire.cs editor marker | FormController.js | Bound questionnaire ID for this Questionnaire item |
pID | integer | Form controller setup | Form runtime | Participant assigned to this questionnaire copy |
Player state keys
Per-participant scoped state. Set via $.setPlayerScriptableValue(playerHandle, <key>, <type>, <value>).
LUIDA does not currently use player-state keys for first-class features. Common in custom code for per-participant flags (e.g., "this participant has completed the practice round").
Signals (sendSignalCompat)
Signals are pulse events — fired with $.sendSignalCompat(<scope>, <signal-name>). Listeners react.
| Signal | Sent by | Received by | Effect |
|---|---|---|---|
state_triggerTransition | "To next state" action; LuidaToNextStateGimmick; participant interactions wired to advance state | StateMachine prefab | Advance state_currentID |
exp_playersAreEnough | ParticipantManager.js when joined count ≥ pNum | StateMachine init logic | Begin first state transition |
exp_StartStateTransition | ParticipantManager.js after between-subjects conditions are saved | StateMachine init logic | Kick off state_currentID = 0 |
exp_readyToLeaveTrials | ConditionManager.js when trialID >= trialCount - 1 | Optional listener (researcher-wired) | Signal end of trial loop; usually wires to UI prompt |
exp_resetTrials | ConditionManager.js (manual reset, debug only) | Trial loop logic | Reset exp_trialID = 0 |
exp_recordCustomData | "Process and Save" action; LuidaProcessDataAndSaveToCollectionGimmick | CustomDataUploader.js | Snapshot collected data into queue |
exp_uploadCustomData | "Upload" action; LuidaUploadCollectedDataGimmick | CustomDataUploader.js | Flush queue to Web Console |
luida_avatar_cmd_reset | AvatarManager.js after processing a command | LuidaAssignAvatarGimmick (resets state to 0) | Reset avatar command flags |
form_allPlayersCompleted | FormController.js when all participants in session have submitted | Optional state-machine listener | Triggers state advance after questionnaire |
form_show_start_hint | FormController.js while waiting for participants | Form prefab UI elements | UI hint visibility |
form_show_loading_bar | FormController.js during questionnaire data fetch | Form prefab UI elements | Loading indicator |
Player-script messages
These are sent via playerHandle.send(<messageType>, <payload>) from the server-side script to the participant's local player script (LuidaBasicPlayerScript.js).
| messageType | Payload shape | Effect |
|---|---|---|
haptics | { target: "left" | "right" | null, frequency, amplitude, duration } | Plays haptic on local controller |
sendOsc | { address: string, values: array } | Sends OSC message from local client |
initializeParticipant | {} | Triggers per-participant init handshake |
setQuestionnaireUI | { uiElementName, props } | Updates one questionnaire UI element |
setQuestionnaireUIs | { updates: array } | Batched update |
clearQuestionnaireAnswerUIs | {} | Disable answer-option labels |
$.groupState keys
Server-side per-instance object cache (not the same as state keys above; this is a JavaScript object, not Cluster's typed state).
| Field | Type | Set by | Read by |
|---|---|---|---|
$.groupState.participants | PlayerHandle[] | ParticipantManager.js on each join | Everywhere (PARTICIPANTS[i] is a thin wrapper) |
$.groupState.sessionID | string | ParticipantManager.js after eligibility | Data calculator scripts |
$.groupState.currentCondition | { varName: value, ... } | ConditionManager.js at trial-boundaries | CONDITION[varName] lookups in actions and data calculator |
$.groupState.stateNames | string[] | Generated state-machine code | Mostly for debugging |
$.groupState.collectedData | object | SendDataToCollector action | calculateData() in your data calculator |
$.groupState.isParticipantsEnough | boolean | ParticipantManager.js | Logic gating session start |
$.groupState.qCompletedCount | integer | FormController.js | Track questionnaire completion progress |
See also
- Concepts → State machine & trial lifecycle — how
state_currentIDandexp_trialIDinteract. - Reference → Variables in scripts —
CONDITION,PARTICIPANTS,COLLECTED_DATA.