Purpose: This page serves as a guide for world creators looking to implement custom-shaped VRChat mirrors that go beyond the standard Unity "Quad" geometry.
We will explore how to set up the necessary components to use a custom mesh as a reflective surface. Additionally, we will discuss the technical details of the 32-bit Layer Mask used by the native VRChat mirror script, helping you control exactly what is and isn't visible in the reflection.
Details: Unity 2022.3.22f1, VRChat SDK - Worlds 3.9.0, VRChat Package Resolver Tool 0.1.29, VRChat SDK - Base 3.9.0, ProBuilder 5.2.4.
Last Edit: 14 November 2025 (Baste~)
Mirrors in VRChat consist primarily of 3 components:
Mesh Renderer
Mirror Reflection Material
VRC Mirror Reflection Script
Both the Reflection Material and VRC Mirror Reflection Script can be found already included in the VRCSDK.
-MirrorReflection Material: Packages/com.vrchat.base/Runtime/VRCSDK/Sample Assets/Materials/MirrorReflection.mat
-VRC Mirror Reflection Script: Packages/com.vrchat.worlds/Runtime/VRCSDK/Plugins/VRCSDK3.dll
In my testing, I have found that many meshes struggle to properly handle the VRC Mirror setup; however, the "Poly Shape" tool from ProBuilder, when created with 0 extrusion and with all vertices individually snapped to a single, flat plane, handles the components just fine. This likely means that creating more complex shapes is also possible with this technique, I myself have made a rounded mirror in my Optimized Mirror prefab. Objects that lack any additional rotation (all 0s) in the inspector seem to handle the VRC Mirror components better than objects you have rotated.
Managing exactly which objects are visible in a VRChat mirror's reflection is handled using a 32-bit LayerMask. This mask is critical for performance because it tells the reflection camera which layers of objects it can skip rendering, saving significant resources.
This setting is referenced and modified in code using the mirror's script component, typically: VRC_MirrorReflection.m_ReflectLayers.
Every GameObject in a Unity scene is assigned to one of 32 possible layers (Layer 0 to Layer 31). The LayerMask is an integer where each of the 32 bits corresponds to a specific layer:
Layer 0: The first bit (rightmost) controls the visibility of Layer 0.
Layer 31: The last bit (leftmost) controls the visibility of Layer 31.
If a bit is set to 1, the corresponding layer is visible in the reflection; if it's set to 0, it is invisible.
// Create a variable for our VRC Mirror script that we will be modifying so that we can link it together in unity.
public VRC_MirrorReflection TargetMirrorScript;
// This lets us retrieve the 32-bit LayerMask in an int format. It is important to know that outputting this will give you the base-10 number not binary.
int CurrentBitMask = TargetMirrorScript.m_ReflectLayers.value;
//This code lets us make a int that will specify a single layer
Int Layer; //Takes a number (IE "6" for layer 6, "9" for layer 9)
int BitMask = 1 << Layer; // This left shifts a 1 based on which layer we are going to, Layer = 4 would be 10000 (Remember counting starts at 0)
//We can then take our designated layer and the CurrentBitMask and use the XOR operation to flip our chosen bit
int NewMask = CurrentBitMask ^ BitMask;
//Finally we can write our new mask back to the VRC_MirrorReflection script to change what layers are visible in game.
TargetMirrorScript.m_ReflectLayers = NewMask;