Unique avatar per participant
Assign a researcher-supplied VRM to each participant — same avatar every session, or a different one per condition.
Goal
Replace the participant's normal Cluster avatar with a VRM you supply. Either everyone in the experiment gets the same one, or you assign a different avatar per condition for an embodiment manipulation.
Smallest setup
- A LUIDA scene with at least one state.
- A
.vrmfile you can use as the assigned avatar. - A Web Console experiment registered (so you can set
participantAvatarMode = HIDE).
This recipe is the short version of Tutorial 2 — Priming + Proteus Effect (with LUIDA automation). If you've never done avatar assignment before, do the tutorial once — there are three settings that need to line up and the tutorial walks them all. This page is the lookup-when-you've-forgotten version.
The recipe
Wrap the VRM in the LUIDA avatar wrapper
Import the .vrm into Unity (UniVRM auto-converts it to a prefab). Duplicate the example wrapper from Assets/ClusterMetaverseLab/LuidaExpTemplate/Runtime/Prefabs/Avatars/ and drag the VRM into the wrapper's slot. Save the wrapper somewhere like Assets/_Experiment_/Avatars/my_avatar_wrapper.prefab.
The wrapper provides the CCK Item and AvatarSyncClone.js script — the VRM alone won't animate.
Register the wrapper
LUIDA › Configure avatars → + Add Avatar. Enter my_avatar as the avatarID, drag the wrapper prefab into the slot. Save.
Set participantAvatarMode = HIDE in the Web Console
On the experiment detail page, scroll to World & Platform, set Participant Avatar to HIDE. Save.
Without this, the participant's normal Cluster avatar renders behind your assigned VRM — you'll see double.
Add the assign action on entry
In LUIDA › Configure experiment automation → State-listening Items, find a controller item (any state-listener-bearing GameObject) at the first state of the experiment. Under On State Start, add:
- Action: AssignAvatarToParticipant
avatarID:my_avatarparticipantIndex:1
Add the unassign action on exit
In the same row, under On State Exit of the experiment's End state, add:
- Action: UnassignAvatarFromParticipant
participantIndex:1
Press Play in CSEmulator. The participant's view shifts to the assigned avatar at the start, follows their head and hands throughout the experiment, and disappears at the end.
Why this works
AssignAvatarToParticipant spawns the wrapper prefab as a CCK item at the participant's current world position, then AvatarSyncClone.js reads the participant's bone transforms each frame and applies them to the wrapper. The participant's underlying Cluster avatar is still rendered behind it — participantAvatarMode = HIDE is what makes the underlying avatar invisible so only your wrapper shows.
The wrapper is just a regular CCK item under the hood. The participant doesn't "become" the avatar; they're still controlling their own (now-hidden) Cluster avatar, and the wrapper is a separate visible item that mimics them. This is why bone-attached props (SyncWithParticipantBone) work alongside it without conflict.
See Concepts → Conditions, sessions, participants for how the participant index is resolved, and Editor → Configure avatars for the registry's full UI.
Variants
Different avatar per condition (embodiment manipulation). Add a between-subjects variable role: doctor,control. Register two wrappers (doctor_coat and trainee_outfit). Use the if toggle on the action row:
if (CONDITION["role"] === "doctor") {
AssignAvatarToParticipant("doctor_coat", 1);
} else {
AssignAvatarToParticipant("trainee_outfit", 1);
}LUIDA's balancer alternates role across sessions; each participant gets exactly one of the two avatars for the full session.
Two participants, different avatars each. For a dyad study (pNum = 2):
AssignAvatarToParticipant("instructor_outfit", 1);
AssignAvatarToParticipant("trainee_outfit", 2);Pair with two unassigns on End:
UnassignAvatarFromParticipant(1);
UnassignAvatarFromParticipant(2);Mid-experiment avatar swap. Add another AssignAvatarToParticipant("different_avatar", 1) on a later state's On State Start. The action despawns the prior wrapper before spawning the new one — safe to call repeatedly. No explicit unassign needed between the two assigns.
Avatar from the Web Console instead of Unity-side. Upload the VRM via the Web Console's Avatars tab. The runtime falls back to the Web Console registry if the Unity-side AvatarRegistry doesn't contain the ID. Mostly useful for swapping avatars without rebuilding the Unity project.
Defensive unassign at experiment start. If you're worried about state leaking between sessions:
// Very first On State Start of the experiment
UnassignAvatarFromParticipant(1);
AssignAvatarToParticipant("my_avatar", 1);The unassign is a safe no-op if there's nothing to clean.
Common pitfalls
avatarIDmismatch.AssignAvatarToParticipant("My_Avatar", 1)won't find anything registered asmy_avatar. Case-sensitive, exact string match.- Forgetting
HIDEmode. WithUNRESTRICTEDorDEFAULT, you'll see the participant's original avatar rendering behind your wrapper. - Spawning the raw VRM. The wrapper structure (with
AvatarSyncClone.js) is what makes the avatar follow the participant's pose. The raw VRM just sits in world space. - Skipping the unassign. The wrapper persists into the next session if you don't clean up. Always pair an assign with an unassign on a symmetric state boundary.
Where to go next
- Tutorial 2 — Priming + Proteus Effect (with LUIDA automation) — the full 120–150 min walkthrough.
- Reference → AssignAvatarToParticipant — every parameter and side effect.
- Reference → UnassignAvatarFromParticipant — the teardown counterpart.
- Editor → Configure avatars — the registry UI.
- Web Console → Platform & avatars — the
participantAvatarModepolicy. - Web Console → Avatars — the Web Console-side VRM upload (alternative registry).