Join Avatar Meshes and Atlas Materials in Blender

Joining mesh objects and combining materials are separate operations. Blender's Join command can turn several compatible mesh objects into one object, but it preserves their material slots. To reduce material slots and the submeshes they create in Unity, the joined mesh also needs a shared UV layout, atlas textures, and one compatible material.

Recommended workflow

Measure the current renderers and material slots, join only compatible objects, build the atlas as a separate step, and compare the result in Unity before replacing the avatar.

  1. Duplicate the Blender file and record the current mesh and material structure.
  2. Group objects by armature, shader, transparency, and toggle behaviour.
  3. Join one compatible group with Ctrl+J.
  4. Pack its UV islands and create matching atlas textures.
  5. Replace the old material slots with one verified material.
  6. Export and compare skinning, animations, appearance, and SDK statistics.
Mesh count and material count are different

VRChat counts Skinned Mesh Renderers and material slots separately. Joining objects can reduce renderer count, while a texture atlas and shared material can reduce material slots. One operation does not guarantee the other.

Decide What Can Be Combined

Place objects in the same join-and-atlas group only when they can share the same runtime behaviour.

Check Compatible group
Armature Skinned objects use the same intended armature and bone set
Shader Materials use the same shader family and render mode
Transparency Opaque, cutout, and transparent surfaces remain in separate groups when their render states differ
Toggles Objects do not need independent GameObject enable or disable controls after joining
Platform The atlas and shader layout work for every target platform using the group
Resolution Surfaces need similar texel density and can share an atlas without losing important detail

Keep separate objects when they need different shaders, independent object toggles, incompatible blend shapes, different armatures, or very different texture resolution. Combining every visible part into one mesh can make later editing and platform reduction harder.

Record the Starting Point

Before editing, record:

  • the number of mesh objects;
  • the armature modifier used by each skinned object;
  • material slots on every object;
  • shader and render mode for every Unity material;
  • texture maps used by each material;
  • blend shapes and vertex groups that must survive;
  • object-level toggles and animations; and
  • the current VRChat SDK renderer, material-slot, texture-memory, and performance-rank statistics.

This creates a direct before-and-after comparison. A smaller Blender object list is not an optimization if Unity still imports the same material slots or the atlas uses substantially more texture memory.

Join Compatible Mesh Objects

Blender's Join operation is available in Object Mode under Object > Join with the Ctrl+J shortcut.

  1. Save a duplicate .blend file.
  2. Enter Object Mode.
  3. Select only the mesh objects in one compatible group.
  4. Select the object whose name and object-level setup should become the active result last.
  5. Press Ctrl+J.
  6. Rename the joined object clearly.
  7. Inspect its material slots, vertex groups, UV maps, shape keys, and Armature modifier.
  8. Pose the armature and test the areas where the original objects met.

Blender joins materials, vertex groups, UV layers, and vertex-colour data into the resulting object. Existing material assignments remain attached to faces, which is why the joined object can still import with many material slots.

Do not delete the source copy yet

Keep the unjoined avatar until the exported result passes Unity animation, expression, material, platform, and SDK validation checks. Joining can expose duplicate material slots, incompatible modifiers, or shape-key limitations that are easier to repair from the source objects.

Build the Shared UV Layout

An atlas places the group's surface textures inside one larger image. Every material channel needs the same island positions.

  1. Open the joined object in Edit Mode and select the relevant faces.
  2. Open the UV Editor and inspect overlapping or out-of-range islands.
  3. Preserve intentional overlaps only when those faces should display the same pixels.
  4. Use UV > Average Island Scale when surfaces should begin with comparable texel density.
  5. Scale important islands deliberately when a face needs more detail.
  6. Use UV > Pack Islands with enough margin for mipmaps and texture filtering.
  7. Inspect the packed layout at the intended atlas resolution.

Blender's Pack Islands tool moves, scales, and optionally rotates islands while preserving a specified margin. The margin prevents neighbouring atlas regions from bleeding into each other as lower mip levels are sampled.

Create Every Atlas Channel

Build one atlas image for each material input used by the final shader.

Channel Atlas requirement
Base colour Copy or bake each source colour region into its new UV area
Normal Bake or transform normals correctly for the final UV layout; do not treat them as ordinary colour
Metallic or specular Preserve the target shader's expected channels and colour-space handling
Roughness or smoothness Confirm which direction and channel the final shader expects
Occlusion Place corresponding grayscale data in the same island regions
Emission Fill unused areas with a non-emissive value
Masks Preserve every packed channel used by the shader

All atlas images must use the same dimensions, island placement, and padding. A base-colour atlas paired with old normal or mask UVs will produce visibly incorrect shading.

TexTools or another maintained atlas tool can automate parts of this process, but its controls and compatibility depend on the installed Blender and add-on versions. The required result is tool-independent: one consistent UV layout and a matching set of texture maps.

Replace the Material Slots

After verifying the atlas images:

  1. Create one Blender material for the compatible group.
  2. Connect the atlas textures using the intended shader workflow as a preview.
  3. Assign the new material to every face in the joined object.
  4. Remove unused material slots only after confirming no faces reference them.
  5. Check the object in Material Preview and under several light directions.
  6. Confirm transparent or cutout surfaces were not accidentally moved into an opaque material.

The exported object should now have one material slot for that group. If several slots remain, inspect face assignments and remove unused slots rather than assuming Join consolidated them.

Export to Unity

Use the same FBX export and Unity import settings as the working source avatar unless a change is required for the optimized file.

After import:

  1. Confirm the rig and Avatar configuration still validate.
  2. Assign the final Unity shader and atlas textures.
  3. Configure normal maps and numeric mask textures with the correct texture types and sRGB settings.
  4. Check the Skinned Mesh Renderer material array.
  5. Inspect bounds, blend shapes, bone references, and Armature deformation.
  6. Apply the avatar's playable layers, expressions, and PhysBones.
  7. Compare the SDK statistics with the recorded source values.

Do not judge the result from the neutral Scene view alone. Test facial expressions, clothing toggles, locomotion, extreme poses, mirrors, and platform variants.

Measure the Actual Result

VRChat's optimization guidance explains that each material slot on a renderer creates a submesh and generally another draw call. It also recommends limiting Skinned Mesh Renderers because skinning them is relatively expensive.

Compare these values before and after:

Metric Expected result
Skinned Mesh Renderers Lower only when compatible skinned objects were joined
Material slots Lower only after faces use the shared atlas material
Texture memory Equal or lower after atlas resolution and platform compression are considered
Triangles Usually unchanged by Join; atlasing does not simplify geometry
Bones Unchanged unless the rig was deliberately optimized separately
Avatar appearance Equivalent at the intended viewing distances
Toggles and animation Every required state still works

An atlas can increase texture memory when several small maps are replaced by an unnecessarily large sheet. Use Unity's Max Size and platform overrides, then check VRChat's texture-memory statistic rather than relying on source-file size.

Android and Quest Checks

Mobile avatars have stricter renderer, material, texture, and package constraints than PC avatars.

  • Use the same UV layout when PC and Android share the mesh.
  • Export lower-resolution Android texture overrides when the mobile view does not need the desktop atlas size.
  • Use only the mobile avatar shaders permitted by VRChat.
  • Keep transparent surfaces separate and remove them from the mobile version when they are not essential.
  • Recheck performance rank and hard component limits after every platform build.

VRChat recommends atlasing mobile avatar textures and aiming for very few materials, but a visually broken one-material result is not better than a deliberate small set of compatible materials.

Original Video Companion

The original Akalink video demonstrates joining meshes and using TexTools for material consolidation. Use it to understand the older workflow, then verify current Blender menus and add-on compatibility before applying its exact controls.

I joined the meshes, but Unity still shows several materials.

Join preserves face material assignments and material slots. Build matching atlas textures, assign one compatible material to every intended face, and remove only the slots that are no longer referenced.

The joined mesh no longer follows the armature correctly.

Check the joined object's Armature modifier, vertex groups, parent relationship, and bone names against the source copy. Only join skinned objects intended to use the same armature and test extreme poses before export.

The atlas has colour lines between UV islands.

Increase the UV-island margin and extend each atlas region beyond its island boundary. Then inspect mipmaps at distance; a layout that looks correct at full resolution can still bleed at lower mip levels.

The base colour is correct, but the shading is broken.

Confirm the normal, metallic, smoothness or roughness, occlusion, and mask atlases use the same UV layout as base colour. Check normal-map import type, sRGB settings, and the final shader's channel contract.

An outfit toggle stopped working after the join.

The original toggle may have enabled a separate GameObject. Keep independently toggled objects separate or rebuild the feature with a supported animation method designed for the joined mesh.

The atlas reduced materials but increased texture memory.

Lower the atlas Max Size, use platform-specific overrides, remove unused channels, or split surfaces into a few resolution-appropriate groups. Compare VRChat's texture-memory statistic after each change.

TexTools controls do not match the video.

The video demonstrates an older add-on version. Check the installed TexTools documentation and Blender compatibility, or complete the same result with Blender's Join, Average Island Scale, Pack Islands, baking, and material tools.

Official References

Related Guides

Topics: Blender, mesh joining, texture atlases, material slots, avatar optimization