UNITE
Core concepts
Three ideas explain how UNITE works: the teleoperation loop it runs, what a module is, and how a study is described as configuration. Understand these and the module reference reads itself.
The teleoperation loop
UNITE models teleoperation as a loop with two directions. Uplink carries the operator's commands to the robot; downlink carries the robot's feedback back to the operator's display. Each direction can have its own communication condition, which determines when packages are released to the next stage. With no condition configured, the channel delivers packages immediately, providing a baseline for comparison.
One component drives everything. Every study scene contains a single
empty GameObject named TeleroboticsAgent, and its UNITE
runtime component (the Kernel) runs every module attached
to it from Unity's
FixedUpdate at a fixed update rate. Data moves
between stages as typed Package envelopes; the two
communication stages transport those packages and apply delay
without ever reading the payload inside.
Remote Observation & State Capture appears twice because it has two
jobs in one tick: it makes the current snapshot available to
Remote-side Assistance, then packages the updated snapshot for
feedback. The module reference shows this with concrete robot-pose,
robot-state, and robot-view examples.
What a module is
A module is one small, replaceable responsibility in the loop —
reading a device, mapping a command, applying a delay, whatever a
single stage needs to do. In code it's a
TeleroboticsModule attached to the
TeleroboticsAgent, which runs every module it holds in a
fixed, deterministic order each tick.
Modules communicate through typed contracts and published packages, so an implementation can be replaced without changing the rest of the loop. A selected implementation may also receive configured dependencies, such as a vehicle reference, sensor source, or condition asset. The study assigns those implementations and references in the agent's Inspector; optional assistance stages can simply be left empty.
For a concrete implementation, start with the shipped Input Provider example. It shows the class, contract, and placement in the project; the UNITE runtime supplies the timing and publishing.
Remote-side Assistance acts locally on the robot using local observations. Operator-side Assistance (downlink) acts after delayed feedback has been reconstructed and creates effects shown to the operator.
Implementation details
Contracts & packages
Between stages, payloads travel inside a minimal Package
envelope — a payload object, a source timestamp, and a stream id. The
communication and assistance stages pass packages along without
interpreting them, which is why a delay model or a shared-control
technique can be written once and reused across studies. Contracts
themselves are generic — InputProvider<TOutputContract>,
for instance — so a study can define its own payload type while reusing
the shared framework code.
Reproducibility
The agent has an ID (a participant or condition
identifier). At startup it derives a stable seed from that ID and seeds
UnityEngine.Random, so the same ID replays the same
pseudo-random sequence. If a study module needs randomness, draw it from
that seeded source. Using the clock, Guid.NewGuid, or a new
unseeded generator would make otherwise identical runs diverge.
Code dependencies
These are code dependencies, not runtime stages. Your study is built on the locked UNITE Kernel, and the Kernel uses shared types from UNITE Core.
Package
Configuration as a study
A study in UNITE is a configured Unity scene holding one wired
TeleroboticsAgent and its selected module implementations.
It may also use shared configuration assets when the same values must be
reused across scenes or conditions.
A configuration asset is a saved instance of a Unity
ScriptableObject. Its C# class defines the available fields, and
its .asset file stores a named set of values. A module references
the file through an Inspector field. The asset stores configuration data;
it does not run a module or hold runtime state.
Use an asset when a parameter set is shared, named, or part of the
experimental condition. For a value used by only one component, a normal
serialized field is simpler. To create one, define a
ScriptableObject class with CreateAssetMenu, create
an instance from Unity's Assets > Create menu, assign it
to the module, and commit the .asset file with the scene.
m_Name: Fixed-Uplink-2560ms
m_EditorClassIdentifier: Assembly-CSharp::Unite.Demo.EveryMoveYouMake.EveryMoveCommunicationConfiguration
uplinkDelayMilliseconds: 1280
downlinkDelayMilliseconds: 1280
direction: uplink
temporalForm: constant
affectedStream: command
nonDelayDegradation: none
This real demo asset is stored at
Assets/UNITE/Demo/every-move-you-make/Configurations/Fixed-Uplink-2560ms.asset.
The communication condition references it so the same 1,280 ms values can
be used by the generated study scenes.
-
Fixed-Uplink-2560ms— the communication condition (a fixed 2.56 s round trip: 1.28 s uplink and 1.28 s downlink). -
TurtleBot3-WafflePi-Moon— the vehicle model and its parameters. Lunar-Target-300s— the task goal and termination rule.
The demo ships four scenes — condition-baseline,
condition-network, condition-path, and
condition-envelope. They share the same vehicle,
communication, task, observation, and presentation configuration. They
differ in the selected Operator-side Assistance (downlink) implementation and therefore
in the feedback shown to the operator. That is the whole point: to
compare techniques fairly, everything except the technique under test
stays fixed.
Because this study uses shared assets, sharing it means committing the scene and those asset files together. A collaborator opens the scene and runs exactly what you ran, with no apparatus to rebuild.
Same ID, same run. Since the seed
comes from the agent's ID, reusing an ID reproduces the
same study-controlled random sequence — useful for re-running a
participant or condition deterministically.