Contacts¶
Contacts let one part of an avatar notice when it touches another — a hand landing on a head (headpat), two hands meeting (handhold), or simply "am I being touched here." A contact drives an animator parameter, so you react to touch the same way you react to a toggle or a gesture: with an animation. Detection runs on every client locally and costs nothing extra on the wire — only the parameter you drive travels, over the animation sync you already use.
There are two components, and they work as a pair:
| Component (Add Component ▸ Social Scape ▸ …) | Role |
|---|---|
| Contact Sender | An emit-only volume that exists to be noticed. It does nothing by itself. |
| Contact Receiver | A volume that detects overlapping senders and writes a parameter. |
Put a receiver on the object you want to be touch-aware (your head, for a headpat); it reacts to any sender carrying a matching tag.
Tags — how a sender and receiver find each other¶
Each component has a list of collision tags (case-sensitive strings). A receiver reacts to a sender only if their tag lists share at least one identical tag. Tags are the whole matching system — this is not a Unity GameObject tag and not a physics layer; there's no real collision involved at all, just tag matching between two volumes.
Both inspectors have a tag picker: a "+ Built-in tag ▾" dropdown offers the standard body-part tags below, plus
a text field for your own custom tags (Hot, Water, Tail, Ear — anything). A known built-in tag shows a small
● marker so you can tell at a glance which of your tags are standard vs. custom.
The standard body tags already exist on every avatar. At load, each avatar automatically gets senders on its bones carrying these built-in tags, so you don't have to wire them — and each sender carries several tags at once, so a receiver can listen as broadly or as precisely as it needs from the same volume:
| Body part | Tags carried by that one sender |
|---|---|
| Head | Head |
| Torso | Torso |
| Left / right hand | Hand, HandL (or HandR) |
| Left / right foot | Foot, FootL (or FootR) |
| Each fingertip | Finger, FingerL/FingerR, FingerIndex/FingerMiddle/FingerRing/FingerLittle, and the exact combo (e.g. FingerIndexL) |
So a receiver tagged just Hand reacts to either hand, from anyone. One tagged HandL reacts only to a left hand.
One tagged Finger reacts to any fingertip touching it at all; one tagged FingerIndexL reacts only to a left index
finger. Pick the tag that matches how precise your reaction needs to be — use your own custom tags for anything that
should only interact within your own systems (a prop's "am I plugged in" socket, a pet's "pettable" zone).
How many auto senders your avatar gets — Auto Body Senders
The Avatar Descriptor has an Auto Body Senders setting (its Contacts section): Minimal (head, hands, feet), Standard (default) (+ torso, + one generic finger sender per hand), Full (+ all eight individual fingertips for per-digit precision), or Off (place every sender yourself). Placing your own sender with a built-in tag suppresses only that one body part's auto entry — everything else still generates, so you can override a single body part without losing the rest.
Contact Receiver — the three reaction types¶
Set Receiver Type:
- Constant — holds Value while any matching sender overlaps, and resets to 0 when none do. Use for "is something touching me right now."
- On Enter — a one-frame pulse of Value the moment a sender first enters (optional Min Velocity requires the touch to arrive at least that fast, so a light rest won't fire but a real tap will). Use to trigger something.
- Proximity — a float 0→1 by depth: 0 at the edge of the receiver, 1 at its centre. Use for gradual reactions (a blush that deepens as a hand gets closer). Reports the closest sender if several overlap.
The parameter must exist
A receiver's Parameter only does something if you've declared that name in your avatar's animator controller. To have other players see the reaction, also declare it in your Expression Parameters so it replicates. Otherwise the reaction is visible only to you. The receiver's inspector warns you if the parameter isn't declared.
No contact = no-op — your parameter's real value is never touched
A receiver only writes its parameter once it has an actual overlap to report. Before that (including forever, if nothing ever touches it), the parameter is left completely alone — so it stays at whatever your Expression Parameters default or your animator controller set it to. A receiver can never force something off (or on) on its own just by existing. Unticking the component's checkbox (or the "Enabled" toggle) fully disables it — a disabled sender or receiver is excluded from detection entirely, same as any other component.
Shared settings¶
- Root Transform — the transform the volume is attached to (empty = this object).
- Shape — Sphere or Capsule (radius + height along local Y).
- Position / Rotation — local offset from the root.
- Collision Tags — the matching list (max 16 per component).
- Local Only — only interact with the same avatar. Local-only contacts are rank-free (they don't count against the networked budget) — use it for self-only effects.
- Receiver also has Allow Self (react to your own senders, e.g. self-headpat) and Allow Others.
Testing it in the SDK¶
Add the Avatar Animation Preview component and press Play — it
runs the same contact detection the game uses. Reach a hand into a Head receiver and watch the parameter change. No
upload needed.
Examples¶
A headpat reaction¶
Add a Contact Receiver to your head bone, tags HandL + HandR, type Proximity, parameter HeadpatProximity
(declare it in your animator + expression parameters). Drive a blush blendshape or a happy expression from the 0→1
value. Anyone's hand on your head now triggers it.
A handhold¶
Add a Contact Receiver to each hand, tags HandL + HandR, type Constant, parameter Holding. When another
player's hand meets yours, Holding goes true — play a gentle finger-curl pose.
Rules & limits (avatars)¶
- There's a contact budget — 32 components (senders + receivers that are not Local Only) on a PC avatar; over the budget the extras are trimmed on upload. Local-only contacts have a much higher ceiling (256). Mark self-only contacts Local Only to keep them off the main budget.
- 16 tags per component; radius up to 3 m; capsule length up to 6 m. Past these the component is clamped.
- Detection is avatar-to-avatar (and world-to-avatar — a sender on a world prop can touch an avatar's receiver).
- Contacts never move anything — they only detect and drive a parameter. Combine them with an animation, a Social Bone, or a constraint to make something visibly happen.
Players can opt out
Each player has Comfort settings — "React to my own contacts", "Let others' contacts affect me", "Let my contacts affect others". A reaction that depends on another player's contact may not fire if they've turned it off, so design reactions to degrade gracefully.
Component class names (for scripts and search): SSContactSender, SSContactReceiver.