Destructible Mesh sample
Updated: May 7, 2026
This sample demonstrates how to segment and dynamically destroy the global mesh in a mixed reality environment using the Mixed Reality Utility Kit (MRUK). It shows event-driven mesh lifecycle management, raycast-based destruction with controller input and hand tracking fallback, and procedural mesh manipulation techniques for developers building interactive spatial experiences on Meta Quest 3 and Quest 3S.
- Use DestructibleGlobalMeshSpawner to create segmented, destructible versions of the global mesh
- Transform mesh segments during segmentation using event callbacks
- Set up physics raycasting against dynamically created mesh segments
- Implement controller-based and hand-tracking-based interaction with spatial meshes
- Manage mesh lifecycle events using C# delegates and UnityEvents
- Meta Quest 3 or Quest 3S (also supports Quest Link)
- Unity 2022.3.15f1 or newer
- Mixed Reality Utility Kit v201.0.0 or newer
- Meta XR Core SDK v201.0.0 or newer
- Room setup with global mesh anchor data
For platform setup instructions, see Unity development setup.
Clone or download the Unity-MRUtilityKitSample repository from GitHub. Open the project in Unity 2022.3.15f1 or newer. Navigate to Assets/MRUKSamples/DestructibleMesh/ and open DestructibleMesh.unity. Build and deploy to your Meta Quest 3 or Quest 3S device using the standard Unity build process.
The sample includes a single scene with a script that manages the destructible mesh lifecycle.
| Component | Location | Purpose |
|---|
Scene file | Assets/MRUKSamples/DestructibleMesh/DestructibleMesh.unity | Main sample scene with prefab references |
Main script | Assets/MRUKSamples/DestructibleMesh/Scripts/DestructibleMeshExperience.cs | Event subscription, mesh transformation, raycast destruction |
When you run the sample, it validates that your device supports global mesh destruction (Quest 3 or Quest 3S) and that room setup data with a global mesh anchor is available. If either check fails, the sample displays an error message.
Press the A or X button on either controller to segment the global mesh into destructible pieces. Point at any segment and pull the index trigger to destroy it. The sample preserves one reserved segment that cannot be destroyed. Press B or Y to remove the destructible mesh entirely. Hand tracking is supported as a fallback to controllers for raycasting.
The sample demonstrates several patterns for working with MRUK’s destructible mesh API.
Event-driven mesh lifecycle
The sample uses two distinct event types: a C# delegate (OnSegmentationCompleted) for transformation callbacks that modify and return segmentation data, and a UnityEvent (OnDestructibleMeshCreated) for notification callbacks that receive the created mesh component. Both subscriptions occur in OnEnable() and unsubscribe in OnDisable() following Unity lifecycle best practices.
// From DestructibleMeshExperience.cs — OnEnable()
destructibleGlobalMeshSpawner.OnSegmentationCompleted += AddBarycentricCoordinates;
destructibleGlobalMeshSpawner.OnDestructibleMeshCreated.AddListener(OnDestructibleMeshCreated);
The OnSegmentationCompleted callback demonstrates a transformation pipeline that modifies mesh data during segmentation. The sample creates new copies of all segments with barycentric coordinates injected as vertex colors. Each triangle receives unique vertex copies (unindexed mesh) so each vertex can store a distinct barycentric value — (1,0,0), (0,1,0), or (0,0,1) — enabling per-triangle visual effects in a custom shader.
Physics setup for raycasting
After the SDK creates mesh segments, the sample adds a MeshCollider component to each segment GameObject. The SDK does not add colliders automatically; this step is required for Physics.Raycast to detect segments. The code retrieves all segments via GetDestructibleMeshSegments() and iterates to configure colliders.
// From DestructibleMeshExperience.cs — OnDestructibleMeshCreated()
destructibleMeshComponent.GetDestructibleMeshSegments(_globalMeshSegments);
foreach (var globalMeshSegment in _globalMeshSegments)
globalMeshSegment.AddComponent<MeshCollider>();
Reserved segment protection
The sample demonstrates the reserved segment pattern: one segment is preserved and cannot be destroyed. The raycast destruction logic compares the hit GameObject against ReservedSegment before calling DestroySegment(). This prevents total mesh destruction and maintains a visual anchor.
The sample implements a priority chain for ray origin: right Touch controller, left Touch controller, right hand PointerPose, then center eye anchor (for editor or headset-off scenarios). This ensures interaction works across controllers and hand tracking without requiring separate code paths.
- Replace barycentric coordinate injection with custom vertex data such as damage values, heat maps, or procedural texture coordinates
- Implement progressive destruction by shrinking segments over time instead of instant removal, or apply physics forces to segments before destruction
- Add visual or audio effects at the destruction point, or spawn particle systems when segments are destroyed