Add Collision Audio to VRChat World Objects
Collision audio makes pickups and physics props feel responsive, but an unfiltered collision callback can produce a burst of overlapping sounds from every small bounce. This guide builds an impact-audio system with the correct collision event, spatial falloff, a minimum impact speed, a short cooldown, and a clear multiplayer playback rule.
Confirm physics first, then add one filtered and spatialized sound response.
- Create a moving object with a Rigidbody and non-trigger Collider.
- Add an AudioSource, VRC Spatial Audio Source, and one short impact clip.
- Handle the correct collision event and ignore impacts below a minimum relative speed.
- Add a cooldown so repeated contacts cannot flood the AudioSource.
- Test the prop locally and with multiple VRChat clients before expanding the system.
VRC Spatial Audio Source adds VRChat's 3D spatialization to a Unity AudioSource. Use it for a physical impact so the sound comes from the prop and fades over an appropriate distance.
Video Companion
Fionna's CyanTrigger tutorial demonstrates the original collision-audio setup. Use it for the visual event-and-action workflow, then apply the current collision selection, filtering, spatial audio, and multiplayer checks below.
Video creator: Fionna
Choose the Collision Event
Use the event that matches what is colliding.
| Interaction | Event | Notes |
|---|---|---|
| Moving physics object touches another Collider | Unity OnCollisionEnter in UdonSharp, or the equivalent supported event in the selected Udon tool |
Provides collision information, including relative velocity and contact data. |
| Moving object collides with a player's capsule | OnPlayerCollisionEnter |
VRChat's player collision event identifies the affected player. |
| Player enters a non-solid area | OnPlayerTriggerEnter |
Use a Collider with Is Trigger enabled. |
| Player walks into a stationary solid object | A trigger volume is usually the reliable player-detection choice | VRChat documents player collision events as events for moving objects. |
| Particle collides with a player | OnPlayerParticleCollision |
Requires Particle System Collision and Send Collision Messages. |
Do not use a trigger Collider for object impact physics. A trigger detects overlap without producing the solid contact response expected from a dropped or thrown prop.
Build the Physics Object
For an object-to-object impact:
- add a Rigidbody
- add a non-trigger Collider
- add an UdonBehaviour, UdonSharpBehaviour, or CyanTrigger behaviour
- add an AudioSource
- add VRC Spatial Audio Source
- add VRC Object Sync when the physical transform must be synchronized
Unity sends collision events when the Collider and Rigidbody requirements are met. At least one of the colliding objects must have a non-kinematic Rigidbody for OnCollisionEnter.
Start with one object and one floor Collider. Confirm the prop falls, collides, and settles before adding audio logic.
Configure the Impact AudioSource
Use a short, dry impact clip that matches the prop's material and scale.
Recommended starting configuration:
| Setting | Purpose |
|---|---|
| Play On Awake | Off, so the clip only plays after an accepted impact. |
| Loop | Off for one-shot impacts. |
| Audio clip | A short transient without long silence at the beginning. |
| VRC Spatial Audio Source | Enabled for positional 3D playback. |
| Near | Keep close to the source unless the object represents a large sound emitter. |
| Far | Limit the sound to the area where the impact should reasonably be heard. |
| Volumetric Radius | Leave at zero for a normal point-like prop unless a larger source is intentional. |
VRChat recommends keeping the VRC Spatial Audio Source Near value at zero for realistic spatialization and leaving Volumetric Radius at zero unless the larger-source behaviour is specifically required.
Filter by Impact Speed
Unity's Collision.relativeVelocity reports the relative linear velocity of the two colliding objects. Its magnitude is a useful input for deciding whether a contact deserves a sound.
Use this flow:
OnCollisionEnter
→ read relative impact speed
→ reject impacts below the minimum threshold
→ reject impacts during the cooldown
→ choose clip and volume
→ play one shot
→ record the playback time
A threshold removes sound from tiny contacts while the object is settling. Tune it with real drops and throws rather than copying a value from an unrelated prop.
Scale Volume Carefully
Map the accepted impact speed to a controlled volume range:
| Impact | Result |
|---|---|
| Below threshold | No sound. |
| Light accepted impact | Quiet variation. |
| Medium impact | Normal playback level. |
| Hard impact | Louder playback, capped at the system's maximum. |
Clamp the final value. An unusually fast physics frame should not produce an unexpectedly loud sound.
Keep source clip levels consistent before relying on runtime volume scaling. A set of clips with very different mastered loudness will not respond predictably to one mapping.
Add a Cooldown
One impact can create multiple contacts as an object bounces or scrapes. Add a short cooldown after an accepted sound.
The cooldown should:
- begin only when a sound actually plays
- ignore repeated contacts for the configured interval
- be short enough to allow separate impacts to remain audible
- be tested with the object's worst bounce or rolling behaviour
Unity's PlayOneShot can play a new clip without cancelling an existing one. A cooldown prevents many collision callbacks from stacking several one-shots on the same AudioSource.
Add Clip Variation
After one clip works reliably, add a small group of clips recorded at a similar loudness.
For each accepted impact:
- select one clip from the group
- apply a small controlled pitch or volume variation if required
- play it through the spatial AudioSource
Avoid obvious immediate repetition when the prop is likely to bounce several times. Keep the system bounded; a large clip collection does not fix weak thresholds or missing cooldowns.
Choose Local or Networked Playback
Collision audio is temporary feedback, so it does not need synchronized persistent state. The decision is whether each client can detect and play the impact consistently or whether one client should announce the accepted impact.
| Playback model | Use when | Risk to test |
|---|---|---|
| Local collision playback | Each client observes the collision reliably enough for the prop | Different clients may disagree about timing or whether a borderline impact passed the threshold. |
| Owner-authoritative network event | The object owner decides which impacts are accepted and tells current players to play the sound | Event frequency and latency must remain controlled. |
| Local owner playback only | Only the manipulating player needs feedback | Other nearby players will not hear the impact. |
Do not combine unfiltered local playback with a network event for the same impact; nearby players may hear the sound twice.
Network events are appropriate only for the temporary playback signal. They are not replayed for late joiners, which is correct for an impact that happened before the player arrived.
Add Owner-Authoritative Playback
When one client should decide:
- confirm the local player owns the synchronized prop
- evaluate relative speed and cooldown on that owner
- choose whether the impact is accepted
- send one bounded network event to current players
- play the selected feedback once on each recipient
Keep the event rate below the system's expected collision frequency. VRChat queues events that exceed their configured rate, so collision spam can turn into delayed audio.
If clip choice or volume must match across clients, include a compact deterministic choice in the event design or derive it from shared input. Do not send persistent state for a sound that only needs to happen once.
Synchronize the Prop Separately
VRC Object Sync handles a GameObject's position, rotation, kinematic state, and gravity state. Audio acceptance remains your Udon logic.
Debug these as separate systems:
- Does the prop move consistently for every player?
- Does the correct client own it?
- Does one accepted impact produce one sound?
- Is the sound spatialized at the prop's location?
Correct movement does not guarantee correct collision audio, and correct local audio does not guarantee shared physical movement.
Player Collision Audio
If a moving object should make a sound when it reaches a player:
- use a solid Collider on the moving object
- handle
OnPlayerCollisionEnter - use the returned player reference only for the player-specific logic you need
- apply the same cooldown and playback-scope rules
VRChat warns that player collision events are for moving objects. For a player walking into a stationary location, use a trigger volume instead.
Do not make collision audio depend on damaging or moving the player unless the world system explicitly requires that separate behaviour.
Audio Placement and Falloff
Use the VRC Spatial Audio Source gizmos in Unity to inspect Near and Far distances.
Test from:
- beside the prop
- the edge of the intended interaction area
- the next social area
- behind walls or room divisions
- the world spawn when relevant
The Far distance should not make a small object audible throughout the world. Several impact props with very large audible ranges can make a busy space difficult to understand.
Performance and Comfort Checklist
- Ignore low-speed settling contacts.
- Use a cooldown on every collision-audio prop.
- Keep impact clips short.
- Limit simultaneous overlapping one-shots.
- Keep Far distance appropriate to the prop.
- Avoid extreme gain or pitch changes.
- Do not send a network event for every physics callback.
- Disable unused impact systems outside active play areas when the design supports it.
- Test several props colliding at once.
- Keep collision audio separate from critical gameplay confirmation when players may mute world audio.
Test the Impact System
| Test | Expected result |
|---|---|
| Gentle placement | No sound or a deliberately quiet accepted sound. |
| Normal drop | One spatialized impact sound. |
| Hard throw | Louder but capped playback. |
| Repeated bounce | Distinct impacts without rapid stacked audio. |
| Rolling or resting | No continuous chatter from tiny contacts. |
| Multiple props | Audio remains understandable and bounded. |
| Desktop pickup | Throwing and dropping produce the intended result. |
| VR pickup | Hand release and physical throws behave consistently. |
| Second client | Playback scope matches the selected local or owner-authoritative model. |
| Ownership transfer | The new owner can produce accepted shared impacts. |
| Android target | Clip, physics, and spatial audio remain usable on the target device. |
Use ClientSim for rapid physics and event checks, then test a private VRChat instance with multiple clients for ownership, network timing, and real spatial audio.
Release Checklist
- [ ] The object has a Rigidbody and non-trigger Collider.
- [ ] The selected collision event matches the interaction.
- [ ] The AudioSource does not play on awake or loop.
- [ ] VRC Spatial Audio Source is present.
- [ ] Near, Far, and Volumetric Radius fit the prop.
- [ ] Low-speed impacts are rejected.
- [ ] Accepted impacts begin a cooldown.
- [ ] Runtime volume is clamped.
- [ ] Clip variations have consistent source loudness.
- [ ] The playback model is local or owner-authoritative, not both.
- [ ] Network-event frequency remains bounded.
- [ ] Multiple-prop, multiplayer, ownership, VR, desktop, and Android tests pass.
Troubleshooting
OnCollisionEnter never runs.
Confirm the object has a Collider and that at least one colliding object has a non-kinematic Rigidbody. Ensure Is Trigger is disabled when you need a solid physics collision.
The prop makes sound while resting on the floor.
Raise the minimum relative-speed threshold and add a cooldown. Check whether the Rigidbody or Collider setup causes continuous jitter instead of settling.
One drop produces several overlapping sounds.
Start a cooldown after the first accepted collision and ignore further callbacks until it expires. Remember that PlayOneShot can overlap clips already playing on the AudioSource.
The impact can be heard everywhere in the world.
Confirm VRC Spatial Audio Source is present and reduce its Far distance to the intended listening area. Inspect the spatial-audio gizmos from nearby rooms and spawn.
Other players hear each impact twice.
The system may be playing locally from the collision and again from a network event. Select one playback authority and ensure each accepted impact reaches each listener once.
Networked sounds arrive late after a pile of collisions.
Reduce accepted collision frequency with a speed threshold and cooldown. VRChat queues network events that exceed their rate limit, so do not send every raw physics callback.
A stationary object does not detect a player walking into it.
VRChat documents player collision events as events for moving objects. Add a trigger volume and use OnPlayerTriggerEnter for a stationary player-detection area.
Official References
- VRC Spatial Audio Source
- Udon Event Nodes
- Player Collisions
- VRC Object Sync
- Network Events
- Networking Performance
- UdonSharp Events
- Unity OnCollisionEnter
- Unity Collision.relativeVelocity
- Unity AudioSource.PlayOneShot