Replacing Copies with Instances in Maya
Replacing Copies with Instances in Maya
Sometimes when working in Maya, artists can find themselves duplicating objects without considering how heavy the scene can become. As tech artists, we often need to process scenes to optimize them for performance, and one of the most effective optimizations is converting duplicate copies into instances.
The Problem
When artists duplicate objects in Maya using Ctrl+D, they create full copies of the geometry. If you have 100 trees in a scene, that's 100 separate meshes eating up memory. Instances, on the other hand, reference the same geometry data, dramatically reducing memory usage.
Building a Duplicate Finder Class
Here's how we can build a Python tool to automatically find and replace duplicates with instances:
Step 1: Build a DefaultDict of Lists
We'll use Python's defaultdict to group meshes by their vertex positions. The key insight is that identical meshes will have identical vertex positions.
from collections import defaultdict
import maya.cmds as cmds
class DuplicateFinder:
def __init__(self):
self.duplicates = defaultdict(list)
def get_vertex_positions(self, mesh):
"""Get all vertex positions as a hashable tuple"""
vertices = cmds.xform(
f"{mesh}.vtx[*]",
query=True,
worldSpace=True,
translation=True
)
# Round to avoid floating point precision issues
rounded = [round(v, 4) for v in vertices]
return tuple(rounded)
def find_duplicates(self):
"""Find all duplicate meshes in the scene"""
all_meshes = cmds.ls(type='mesh', long=True)
for mesh in all_meshes:
# Skip intermediate objects
if cmds.getAttr(f"{mesh}.intermediateObject"):
continue
# Get transform node
transform = cmds.listRelatives(mesh, parent=True, fullPath=True)[0]
# Use vertex positions as key
positions = self.get_vertex_positions(mesh)
self.duplicates[positions].append(transform)
# Filter out unique meshes
return {k: v for k, v in self.duplicates.items() if len(v) > 1}
Step 2: Convert to Instances
Once we've found the duplicates, we can replace them with instances:
def convert_to_instances(self, duplicates_dict):
"""Convert duplicate meshes to instances"""
for positions, transforms in duplicates_dict.items():
# Keep the first one as the master
master = transforms[0]
# Convert the rest to instances
for duplicate in transforms[1:]:
# Get transform data
pos = cmds.xform(duplicate, query=True, worldSpace=True, translation=True)
rot = cmds.xform(duplicate, query=True, worldSpace=True, rotation=True)
scale = cmds.xform(duplicate, query=True, worldSpace=True, scale=True)
# Create instance
instance = cmds.instance(master)[0]
# Apply transform
cmds.xform(instance, worldSpace=True, translation=pos)
cmds.xform(instance, worldSpace=True, rotation=rot)
cmds.xform(instance, worldSpace=True, scale=scale)
# Delete the duplicate
cmds.delete(duplicate)
print(f"Converted {len(transforms)-1} duplicates to instances of {master}")
Usage
# Find and convert duplicates
finder = DuplicateFinder()
duplicates = finder.find_duplicates()
finder.convert_to_instances(duplicates)
Results
On a typical environment scene with 500+ objects, this can reduce memory usage by 60-70% and significantly improve viewport performance. The key is identifying truly identical meshes - even a single vertex difference will prevent the conversion.
Caveats
- This only works for meshes with identical topology
- Materials and UV sets must also match
- Consider freezing transforms before running this tool
- Always backup your scene first!
This tool has saved countless hours in optimization passes and is now part of our standard scene cleanup pipeline.