Optimizing for VRChat with Unity
A practical guide for new creators who want their avatars and worlds to run well.
Every optimization here is something you can do today in Unity without advanced knowledge.
Start with textures - they are almost always the biggest win.
Performance Ranks
VRChat assigns every avatar a performance rank: Excellent, Good, Medium, Poor, or Very Poor.
Many users configure their safety settings to hide Poor and Very Poor avatars entirely,
which means they will never see your avatar - just a gray placeholder.
Aiming for Good or Medium ensures most people can actually see your work.
Performance rank is determined by several stats combined. The sections below cover
each stat and what you can do to improve it.
Textures (Biggest Impact)
Textures are the #1 consumer of video memory (VRAM) for most avatars.
A single uncompressed 4096x4096 texture uses 64 MB. Most avatars have 5-15 textures.
This adds up fast.
Use the right resolution
Bigger is not better. Match texture size to how much detail is actually visible.
| Use Case |
Recommended Size |
| Body / main diffuse | 2048x2048 (or 1024 on Quest) |
| Face close-up / detail | 1024x1024 or 2048x2048 |
| Hair, accessories | 512x512 or 1024x1024 |
| Small items (nails, eyes, teeth) | 256x256 or 512x512 |
| Normal / roughness maps | Same as or one step below diffuse |
| Emission masks, simple patterns | 256x256 or smaller |
Always use power-of-two dimensions (256, 512, 1024, 2048, 4096). Non-power-of-two
textures waste memory because the GPU pads them up to the next power of two anyway.
Enable compression
In Unity's texture import settings, set the compression format. Never leave textures
as uncompressed RGBA32 in a build.
| Platform |
Opaque Textures |
Textures with Alpha |
Normal Maps |
| PC |
DXT1 / BC1 (4 bpp) |
BC7 (8 bpp) - preferred over DXT5 at the same VRAM cost |
BC5 (8 bpp) |
| Quest / Android |
ETC2_RGB (4 bpp) or ASTC 6x6 |
ETC2_RGBA8 (8 bpp) or ASTC 4x4 |
ETC2_RGB (4 bpp) or ASTC 6x6 |
Crunch compression (DXT1_CRUNCHED, DXT5_CRUNCHED) reduces the download
size of your avatar but uses the same VRAM as the base format. It is worth enabling for
faster load times, but it does not lower your VRAM rank.
Enable mipmaps
Mipmaps add about 33% more VRAM but significantly improve visual quality at a distance
and can actually improve GPU performance by reducing cache misses. Leave them on for
most textures. The only exception is UI elements or textures that are always viewed at
full resolution.
Atlas your textures
If your avatar has 8 materials each with their own 1024x1024 diffuse texture, that is
8 draw calls and 8 separate texture loads. Combine them into one 2048x2048 atlas and
one material. This cuts both VRAM and draw calls. Tools like
Cats Blender Plugin or Unity's built-in sprite atlas can help.
VRAM reference
Approximate VRAM per texture (with mipmaps, compressed):
| Size |
DXT1 (4 bpp) |
DXT5 (8 bpp) |
RGBA32 (uncompressed) |
| 256x256 | 43 KB | 85 KB | 341 KB |
| 512x512 | 170 KB | 341 KB | 1.33 MB |
| 1024x1024 | 682 KB | 1.33 MB | 5.33 MB |
| 2048x2048 | 2.67 MB | 5.33 MB | 21.33 MB |
| 4096x4096 | 10.67 MB | 21.33 MB | 85.33 MB |
Use the VRAM Budget Calculator API to calculate exact
totals for your texture set.
Meshes and Polygons
Polygon count (triangles) directly affects how much work the GPU does every frame.
Target triangle counts
| Rank |
PC |
Quest |
| Excellent | 32,000 | 7,500 |
| Good | 70,000 | 10,000 |
| Medium | 70,000 | 15,000 |
| Poor | 70,000 | 20,000 |
On PC, triangle count mostly matters for reaching Excellent rank - anything under 70,000
avoids Very Poor for this metric. On Quest the limits are much tighter.
Many purchased avatars ship at 100,000+ triangles, which is Very Poor on PC
and far beyond Quest limits.
How to reduce triangles
- Decimate in Blender - Use the Decimate modifier. Start at ratio 0.5 and
adjust until the silhouette still looks good. Focus on areas players cannot see (inside
of mouth, under clothing layers).
- Delete hidden geometry - If your avatar has a full body mesh under
opaque clothing, delete the covered parts. This is the single easiest win for most
purchased avatars.
- Merge meshes - Multiple mesh renderers create multiple draw calls.
Merge meshes that share the same material into one.
Materials and Shaders
Reduce material count
Every material is a separate draw call. Avatars with 15-20 materials are common from
purchased assets but hurt performance significantly. Target 4 or fewer materials by
atlasing textures so multiple parts can share one material.
Choose efficient shaders
- VRChat/Mobile shaders - Required on Quest, good baseline on PC.
- Standard / Standard (Specular) - Unity's built-in, reasonable performance.
- Poiyomi Toon - Popular community shader. Use the "locked" (optimized) mode
before upload - right-click the material and select Lock. Unlocked Poiyomi is significantly
more expensive.
Avoid transparent/cutout materials when possible. They are more expensive to render than
opaque materials and disable some GPU optimizations.
PhysBones
PhysBones (VRChat's dynamic bone system) run on the CPU every frame. Too many bones or
colliders cause frame drops in crowded instances.
| Stat |
Excellent (PC) |
Good (PC) |
Excellent (Quest) |
Good (Quest) |
| PhysBone components | 4 | 8 | 0 | 4 |
| Affected transforms | 16 | 64 | 0 | 16 |
| Colliders | 4 | 8 | 0 | 0 |
Quest does support PhysBones, but Excellent rank requires zero. If you exceed the
Poor limits on Quest, all PhysBones on the avatar are stripped entirely regardless
of the user's show avatar settings.
Focus PhysBones on things that matter visually - hair and a tail are usually enough.
Remove PhysBones from accessories, clothing edges, and other subtle elements that most
people will never notice.
Audio
- Compress audio clips - Use Vorbis compression at quality 30-50% for most
sound effects. Uncompressed WAV files are dramatically larger in memory.
- Use mono for spatial audio - 3D positional sounds only need one channel.
Check "Force To Mono" in Unity's audio import settings. This halves the memory cost.
- Keep clips short - A 30-second uncompressed stereo clip at 44.1 kHz is
about 5 MB. Consider whether you really need that length.
World-Specific Tips
Bake your lighting
This is the single most impactful optimization for worlds. Baked lighting is calculated
once in Unity and stored as lightmap textures. Realtime lights are calculated every frame
per light per object. Switch all static lights to "Baked" and mark non-moving geometry
as "Static" in the inspector.
Use Occlusion Culling
Occlusion Culling prevents Unity from rendering objects that are hidden behind walls or
other geometry. Open Window > Rendering > Occlusion Culling,
mark your static geometry as Occluder Static and Occludee Static, then bake.
This is especially important for indoor worlds with multiple rooms.
Add LODs
Level of Detail (LOD) groups swap in simpler meshes when objects are far from the camera.
For any detailed prop or set piece, create 2-3 LOD levels. LOD0 is full detail, LOD1 is
roughly 50% triangles, LOD2 is roughly 25%. Unity handles the switching automatically.
Use light probes
Light probes capture baked lighting data at specific points so that dynamic objects
(avatars, pickups) receive realistic lighting without realtime lights. Place them
throughout your world in a rough grid, with more density near lighting transitions
(doorways, windows, colored light boundaries).
Testing Your Work
- VRChat SDK Control Panel - The build panel shows your avatar's stats
and performance rank before you upload. Check it every time.
- Avatar Stats window - In Unity, open the VRChat SDK and check the
avatar's detailed stats. It breaks down polygon count, material count, texture memory,
PhysBone count, and other performance metrics.
- Test on Quest - If you are making a cross-platform avatar, always
test the Quest version on an actual Quest headset. Performance that looks fine on PC
can be unplayable on mobile hardware.
- Frame Timing overlay - In VRChat, enable the frame timing overlay
from the debug menu to see real CPU and GPU frame times in-world.
Quick Wins Checklist
- Set texture compression (DXT1/DXT5 on PC, ETC2/ASTC on Quest)
- Downsize textures that don't need to be 4096
- Delete geometry hidden under clothing
- Merge meshes that share materials
- Atlas textures to reduce material count
- Lock Poiyomi materials before upload
- Remove PhysBones from subtle details
- Bake lighting in worlds
Need to calculate your texture VRAM budget?
Use the VRAM Calculator API