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 diffuse2048x2048 (or 1024 on Quest)
Face close-up / detail1024x1024 or 2048x2048
Hair, accessories512x512 or 1024x1024
Small items (nails, eyes, teeth)256x256 or 512x512
Normal / roughness mapsSame as or one step below diffuse
Emission masks, simple patterns256x256 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)
256x25643 KB85 KB341 KB
512x512170 KB341 KB1.33 MB
1024x1024682 KB1.33 MB5.33 MB
2048x20482.67 MB5.33 MB21.33 MB
4096x409610.67 MB21.33 MB85.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
Excellent32,0007,500
Good70,00010,000
Medium70,00015,000
Poor70,00020,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 components4804
Affected transforms1664016
Colliders4800

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