Documentation Index
Fetch the complete documentation index at: https://dadd.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Two hooks for working with MuJoCo contacts: useContacts for per-frame contact queries, and useContactEvents for enter/exit transitions.
Query contacts involving a specific body (or all contacts).
Signature
useContacts(
bodyName?: string,
callback?: (contacts: ContactInfo[]) => void
): React.RefObject<ContactInfo[]>
Usage
import { useContacts } from "mujoco-react";
function ContactCounter() {
const contacts = useContacts("block_1");
useFrame(() => {
if (contacts.current.length > 0) {
console.log(`${contacts.current.length} contacts on block_1`);
}
});
return null;
}
With Callback
const contacts = useContacts("gripper_left", (contacts) => {
const touchingCube = contacts.some(c =>
c.geom1Name === "cube" || c.geom2Name === "cube"
);
if (touchingCube) console.log("Gripper touching cube!");
});
const allContacts = useContacts(); // No body filter
Subscribe to contact enter/exit transitions for a body.
Signature
useContactEvents(
bodyName: string,
handlers: {
onEnter?: (info: ContactInfo) => void;
onExit?: (info: ContactInfo) => void;
}
): void
Usage
import { useContactEvents } from "mujoco-react";
function CollisionSound() {
useContactEvents("ball", {
onEnter: (info) => {
playSound("bounce", { volume: Math.min(info.depth * 10, 1) });
},
onExit: (info) => {
console.log("Lost contact with", info.geom2Name);
},
});
return null;
}
interface ContactInfo {
geom1: number; // Geom ID of first body
geom1Name: string; // Name of first geom
geom2: number; // Geom ID of second body
geom2Name: string; // Name of second geom
pos: [number, number, number]; // Contact point
depth: number; // Penetration depth
}
Notes
- Contact data is read from
data.contact every physics frame
- Geom names are cached to avoid repeated WASM string lookups — the cache clears on model change
useContactEvents diffs the contact list between frames to detect transitions
- Contact reads are wrapped in try/catch (can fail with large
ncon)
- For a component-based API, see
<ContactListener>