SULLY'S TOOLS

Welcome

Unity Assets

PolyPaint

Vertex colour painting tool for the Unity Editor.

Maya Scripts

Snap Verts to Grid

MEL script that snaps selected geometry to the nearest grid position in Maya.

Feedback

💬
💬

Bugs / Feedback

Report a bug, request a feature, or share a thought about any of the tools.

PolyPaint

A vertex colour painting tool for the Unity Editor.

PolyPaint is an Editor tool for painting vertex colours directly onto meshes in the Unity Scene viewport. It's built for artists and technical artists who want to store per-vertex data (masks, blend weights, tints, and more) without needing additional texture maps.

Key Features

  • Brush-based vertex colour painting directly in the Scene view
  • Paint per-channel (R, G, B, A) individually or in any combination
  • Three brush targets: Vertex, Edge, and Face
  • Three paint modes: Replace, Add, and Erase
  • Fill, Erase All, Clamp, Randomise, and Colour Swap operations
  • Vertex colour transfer between two meshes
  • Snapshot system for saving and restoring paint data as project assets
  • Object Sets for saving and reloading multi-mesh selections
  • Undo / Redo history with configurable step limit
  • Autosave to snapshot at a configurable interval

Setup

Installing PolyPaint and getting started with painting.

Installation

  1. Purchase PolyPaint from the Unity Asset Store.
  2. In the Unity Editor, open the Package Manager via Window → Package Manager.
  3. Select My Assets from the dropdown, find PolyPaint, and click Import.
  4. Once it's imported, open the tool from the menu bar: Tools → PolyPaint.

Requirements

RequirementDetail
Unity VersionTBC
Render PipelineAll (URP, HDRP, Built-in)
PlatformEditor only

Quick Start

  1. Open PolyPaint via Tools → PolyPaint.
  2. Select one or more GameObjects with Mesh Filters in your scene.
  3. Click the Tool Enabled toggle at the top of the window to activate painting.
  4. Choose a colour, brush size, and mode in the Paint section.
  5. Click and drag on your mesh in the Scene viewport to paint.

When the tool is enabled, a brush disc and vertex cloud appear in the Scene viewport over your selected mesh. The status bar at the top of the window tells you when painting is ready.

Opening the Tool

You can open PolyPaint two ways:

  • From the menu bar: Tools → PolyPaint
  • From the Unity Overlay Menu in the Scene view: enable overlays, then find PolyPaint under Custom → PolyPaint

The Scene view overlay is a dockable panel that gives you quick access to the tool toggle, visual options, and undo / redo buttons without needing the main window open.

Targets

Selecting and managing which meshes to paint.

The Targets section shows how many meshes and vertices are currently selected for painting. PolyPaint paints on any selected GameObject with a Mesh Filter component.

Skinned Mesh Renderers, terrain, and meshes without a persistent asset aren't supported and won't appear as targets.

The first time you paint on a mesh, PolyPaint creates a unique instanced copy so only that object is affected. Other objects sharing the same source mesh stay unchanged. This instance is saved to your scene and is what all painting, snapshots, and mesh operations work against.

Options

PropertyTypeDescription
Include ChildrenboolAny children of the selected object(s) with Mesh Filters will also be included for painting.
Include TransparentboolWhether or not to ignore any selected meshes that use transparent materials.

Object Sets

If you regularly paint across the same group of objects, save your current selection as an Object Set asset using Save Selection. You can then restore that exact selection at any time with Select Objects.

ControlDescription
Save SelectionSaves the current scene selection to a reusable Object Set asset.
Object Set fieldAssign a previously saved Object Set asset.
Select ObjectsSelects all objects from the loaded Object Set that exist in the current scene.

Show

Viewport visualisation options.

The Show section controls what's visible in the Scene viewport while you're painting. These options help you see your vertex colour data clearly as you work.

Viewport Options

PropertyTypeDescription
WireframeboolSwitch to Shaded Wireframe draw mode in the Scene viewport.
Brush InfoboolShow a panel attached to the cursor displaying current brush settings.
IsolatedboolHide all other objects in the scene except your current selection.
Debug MaterialboolToggle a temporary material on the selected mesh(es) that visualises the channel being authored - raw vertex colour in Vertex Paint mode, or per-vertex normals in Normals mode. Original materials are restored automatically when you close the tool, change your selection, or switch scenes.
Front Verts OnlyboolFilter out vertices not visible to the camera, including back-facing verts on flat planes. Also limits painting to those visible verts only.
RealtimeboolDraw overlays every frame rather than only when the camera is static. Disabling can improve performance.

Vertex Cloud

The Vertex Cloud shows coloured dots in the Scene viewport representing vertex positions and their current colour values. It gives you a live preview of your painted data without switching materials.

PropertyTypeDescription
Vertex CloudboolDisplay dots in the Scene viewport representing vertex positions and colours.
Draw DistancefloatHow far from the camera to draw the Vertex Cloud. Higher values may impact performance.
Dot SizefloatAdjust the size of the vertex dots in the Scene viewport.

Paint

Brush settings, paint modes, and colour channels.

The Paint section contains all your brush controls.

Mode

The brush works in one of two modes. Vertex Paint authors per-vertex RGBA colour data, which your shaders can use for tinting, masking, baked AO, wind, and more. Normals authors per-vertex normals and edge topology, so you can harden or smooth shading directly in Unity without returning to your 3D application.

Shared Vertices

When a mesh is exported from a 3D application, smooth edges share a single vertex between all adjacent faces. Hard edges work differently. The vertex is split into multiple copies stacked at the same world position, one per adjacent face, so each face can carry its own outward-facing normal. In the scene view this looks like a single vertex, but there can be several hidden beneath it.

PolyPaint's Normals brush can do this splitting and merging for you. Hardening an edge separates those stacked vertices and increases vertex count. Smoothing an edge merges them back into one and lowers it. How this affects Vertex Paint is covered in the panes below.

In Vertex Paint mode the brush authors per-vertex RGBA colour data on your selected meshes. A colour picker and per-channel toggles let you control which colour and which channels the brush writes to.

Operation

This controls how the brush combines its colour with the existing vertex colour.

OperationDescription
ReplaceFully replaces existing vertex colour with the brush colour.
AddAccumulates the brush colour on top of the existing vertex colour.
EraseRemoves vertex colour by transitioning active channels toward black.

Target

Choose which polygon component the brush spreads colour to.

TargetDescription
VertexAffect all vertices within the brush radius.
EdgeAffect all vertices that make up the edges within the brush radius.
FaceAffect all vertices that make up faces within the brush radius.

Shared Verts

Hard edges (whether they came from your 3D application or were painted with Normals mode) are made up of stacked vertices at the same world position. This toggle controls whether Vertex Paint treats those stacked vertices as separate paint targets or as one.

Use Split when you need crisp colour seams that follow your hard edges. For example, painting a different colour on each side of a crease. Use Merge for broad colour work where you want colour to spread across edges naturally without worrying about the underlying topology.

OptionDescription
MergeAll stacked vertices at a position are painted as one. Colour spreads across hard edges regardless of the underlying topology.
SplitEach stacked vertex is a separate paint target. Lets you paint a distinct colour on each face that meets at a hard edge.
A common workflow: harden the edges you want with Normals mode first, then switch to Vertex Paint with Shared Verts set to Split to paint distinct colours on each side of those edges.

Brush

PropertyTypeDescription
RadiusfloatAdjusts the size of the brush cursor in the Scene viewport.
StrengthfloatChanges the strength of the brush stroke. Only shown in Add and Erase operations - Replace always writes at full strength.
FalloffcurveControls the brush falloff from the centre to the edge.
You can drag any field label (Radius, Strength, etc.) left or right to scrub the value quickly.

Channel

Choose which vertex colour channels the brush will affect. Any combination of R, G, B, and A can be enabled. At least one channel must stay active at all times.

When only a single channel is active, the colour picker is replaced with a Value slider that controls the intensity of that channel.

Colour and Swatches

When multiple channels are active, you'll get a full RGBA colour picker. Use the eyedropper to sample a vertex colour directly from the scene. Saved swatches appear below the picker for quick reuse, and you can import a palette from an image file to populate them.

In Normals mode the brush authors edge shading and topology instead of vertex colours. The colour picker and channel toggles are replaced with a normals visualisation. Use this mode to harden or smooth edges directly in Unity. It's the same operation your 3D application performs when you mark an edge as hard or smooth.

Shading

Painting Hard splits the stacked vertices at each painted position apart so every adjacent face gets its own copy with a face-aligned normal. This is what makes a visually sharp crease, and it does increase vertex count. The benefit is that those vertices are now separate, so Vertex Paint's Split mode can paint each face's corner independently and give you crisp colour seams along the crease.

Painting Smooth does the opposite. It averages the normals at each painted position and merges stacked vertices back into one shared vertex when they fully agree. Vertex count drops, and colour in Vertex Paint blends naturally across the join. UV seams are always preserved either way.

ShadingDescription
SmoothAverages normals and merges stacked vertices back into one where they agree. Vertex count drops. Colour in Vertex Paint blends across the join.
HardSplits stacked vertices apart and assigns each its face normal. Vertex count grows. Vertex Paint can then target each face's corner independently with Split mode.

Target

Choose which polygon component the brush spreads to.

TargetDescription
VertexAffect all vertices within the brush radius.
EdgeAffect all vertices that make up the edges within the brush radius.
FaceAffect all vertices that make up faces within the brush radius.
Use the Edge target with Hard shading to crease a single edge without splitting the surrounding geometry.

Brush

PropertyTypeDescription
RadiusfloatAdjusts the size of the brush cursor in the Scene viewport.
FalloffcurveControls the brush falloff from the centre to the edge.
Normals mode has no Strength control - every stroke fully commits the chosen Shading at the painted positions.

Actions

Mesh-wide colour operations.

The Actions section gives you operations that apply across all vertices on your selected mesh(es) at once, rather than painting by hand. The available actions depend on the current Paint Mode. The Mesh Management buttons at the bottom of the panel are always shown.

Fill, Erase All, Clamp

All three actions respect your currently active channel selection.

ActionDescription
Fill AllFills all vertices with the current brush colour. Only applies to the currently selected channels.
Erase AllSets all vertices to black. Only applies to the currently selected channels.
Clamp AllRounds all vertex colours up or down to 0 or 1. Only applies to the currently selected channels.

Randomise

Applies a random value to every vertex using the current Operation (Replace, Add, or Erase). Use the Min and Max fields to set the range.

Colour Swap

Replaces all vertices on your selected mesh(es) that match a Target colour with a New colour. Increase the Threshold to also swap colours that are close to, but not exactly, the target. Both colour pickers support the eyedropper so you can sample directly from a vertex in the scene.

PropertyTypeDescription
TargetcolorThe colour to search for and replace on the mesh.
NewcolorThe colour to apply to matching vertices.
ThresholdfloatIncrease to also match colours that are close to the target colour.

Vertex Colour Transfer

Transfers vertex colours from one mesh to another based on world-space proximity. It's great for high-to-low mesh baking workflows and for spreading painted lighting or colour gradients across multiple objects.

Select exactly two meshes for this feature to become available.
PropertyTypeDescription
SourceGameObjectThe mesh to transfer vertex colours from.
TargetGameObjectThe mesh to receive the transferred colours.
DistancefloatControls how far the transfer can reach from source vertices to target vertices.
PreviewtoggleShow arrows in the Scene viewport from each source vert to its nearest matched target vert before committing.
Target vertices beyond the Distance threshold are left unchanged. Increase Distance if the result looks incomplete.
Transfer is destructive. Use Undo if you need to roll back.

Set Shading

Mesh-wide normals operations. Verts in flat regions (where shading can't vary) are skipped.

ActionDescription
Fill SmoothSmooth every edge on the mesh where shading can vary. Stacked vertices merge back into one shared vertex, lowering vertex count.
Fill HardHarden every edge on the mesh where shading can vary. Stacked vertices are split apart so each face gets its own copy with a face-aligned normal, increasing vertex count.
SwapInvert every non-flat position's shading - hard edges become smooth and smooth positions become hard.

Normal Transfer

Transfers vertex normals from one mesh to another based on world-space proximity. It's useful for high-to-low mesh workflows where you want the low-poly to inherit the shading of the high-poly.

Select exactly two meshes for this feature to become available.
PropertyTypeDescription
SourceGameObjectThe mesh to transfer normals from.
TargetGameObjectThe mesh to receive the transferred normals.
DistancefloatControls how far the transfer can reach from source vertices to target vertices.
PreviewtoggleShow arrows in the Scene viewport from each source vert to its nearest matched target vert before committing.
Target vertices beyond the Distance threshold are left unchanged. Increase Distance if the result looks incomplete.
Transfer is destructive. Use Undo if you need to roll back.

Mesh Management

ActionDescription
Re-Import Mesh(es)Re-imports the selected mesh(es) from their source files, while preserving the current scene transform, material, and vertex paint data. Vertex paint may be distorted on any vertices that no longer match their previous positions. The scene is saved automatically. This button exists because PolyPaint adds a "Poly Paint Instance" suffix to the mesh filter, causing Unity to lose its automatic import reference to the source asset.
Reset Mesh(es)Removes the PolyPaint instanced mesh filter and restores the original mesh asset. The scene is saved automatically.
Both Re-Import and Reset can't be undone and will clear the History undo and redo stacks entirely.

Snapshot

Saving and restoring vertex colour data as project assets.

The Snapshot system lets you persist vertex colour data to a Snapshot asset in your project. You can then apply that data back to any matching mesh at any time, even across different scenes, using a configurable world-space distance threshold to match vertices.

Source

OptionDescription
Current SelectionUses the currently selected scene objects as the source.
Object SetUses the meshes defined in a saved Object Set asset, regardless of current selection.

Save and Apply

ActionDescription
Save to SnapshotWrites current vertex colours from the source to the loaded Snapshot asset.
Apply from SnapshotReads vertex colour data from the Snapshot and applies it to source vertices by world position.
Apply overwrites matched vertices only. Unmatched vertices (beyond the distance threshold) are left unchanged.
Snapshots store world-space positions. Moving, rotating, or scaling a mesh between save and apply will break vertex matching.

Autosave

PropertyTypeDescription
AutosaveboolAutomatically save the source selection to the loaded Snapshot at a set interval.
IntervalfloatHow often (in minutes) to autosave. Supports fractional values for sub-minute intervals.
Autosave overwrites the loaded Snapshot on every interval. Make sure the correct Snapshot is loaded before enabling it.
When using Current Selection, autosave pauses if nothing is selected. Use an Object Set as the source for uninterrupted autosave.

History

Undo and redo vertex colour changes.

The History section gives you undo and redo for paint operations. PolyPaint manages its own undo stack independently from Unity's built-in undo system.

Ctrl+Z and Edit > Undo won't undo paint strokes - use the Undo and Redo buttons here instead.
PropertyTypeDescription
Max StepsintMaximum number of undo states kept in memory. Range: 1–99. Default: 25.
UndobuttonReverts the last paint operation.
RedobuttonRe-applies the last undone operation. Cleared as soon as a new action is performed.

Limitations

History is in-memory only. It's lost when the tool closes, on script compilation, or when Re-Import Mesh or Reset Mesh is run.
For a restore point that survives any of the above, save a Snapshot before starting a session you might want to roll back.

Object Sets

Save and restore multi-mesh selections as reusable assets.

An Object Set is a ScriptableObject asset that stores a list of scene objects by their hierarchy path. Save your current selection to an Object Set and restore it at any time, even across sessions.

Creating an Object Set

  1. Select the objects you want to save in the scene.
  2. In the Targets section, click Save Selection.
  3. Choose a save location in your project. The asset is created and automatically loaded into the Targets section.

Using an Object Set

Assign an Object Set to the Object Set field in the Targets section, then click Select Objects to restore the selection. Any objects that no longer exist in the scene are skipped with a console warning.

Object Sets can be used as the Source for Snapshot save and apply operations. That means you can save and restore paint data without needing anything selected in the scene.

Creating via Menu

You can also create Object Set assets directly from the Project window via Create → PolyPaint → Object Set.

Snapshots

The Snapshot ScriptableObject asset.

A Snapshot is a ScriptableObject asset that stores a list of vertex world positions and their associated colours. It's a portable, persistent record of your vertex colour data that lives right in your project.

What Gets Stored

Each entry in a Snapshot stores:

  • World Position - The position of the vertex in world space at the time of saving.
  • Colour - The vertex colour as a Color32 value (RGBA, 0–255 per channel).

Creating a Snapshot Asset

You can create Snapshot assets two ways:

  • From the Snapshot section in the PolyPaint window using the New button.
  • From the Project window via Create → PolyPaint → Vertex Colour Snapshot.
The point count shown in the Snapshot panel tells you how many data points are stored in the asset versus how many vertices are on the source mesh. They don't need to match. Data is matched by world position proximity.

Frequently Asked Questions

Common questions about PolyPaint.

General

Does PolyPaint work with URP, HDRP, and the Built-in Render Pipeline?

Yes. PolyPaint is an Editor-only tool that modifies vertex colour data directly on meshes. It's render pipeline agnostic. That said, your shader needs to read and use vertex colours for the painted data to be visible at runtime.

Does PolyPaint add anything to my build?

No. PolyPaint is entirely Editor-only. No scripts, components, or assets are included in your build unless you explicitly place them there yourself.

Will it work on any mesh?

PolyPaint works on any GameObject with a Mesh Filter component. It doesn't support Skinned Mesh Renderers, terrain, or procedurally generated meshes that don't have a persistent Mesh asset. See the Targets page for more on what qualifies as a valid target.


Painting

The tool is enabled but nothing is happening when I click in the Scene view.

Check the status bar at the top of the PolyPaint window. It'll tell you exactly what's wrong. The most common causes are:

  • No GameObject is selected, or the selected object has no Mesh Filter. See Targets.
  • The selected mesh uses a transparent material and Include Transparent is disabled. Also on the Targets page.
  • You're clicking outside the Scene viewport, or another tool (e.g. the Transform tool) is intercepting input.

My brush is painting but I can't see the colours in the viewport.

Enable Debug Material in the Show section to apply a temporary debug material that displays raw vertex colour values. If your shader doesn't sample vertex colours, the data is still there. It just won't be visible with your regular material.

My redo history disappeared when I painted something after undoing.

That's expected. As soon as you perform a new action after undoing, the redo stack is discarded. If you want a restore point you can always return to, save a Snapshot before starting a paint session. Snapshots aren't affected by the undo stack.

Painting seems slow or the Scene view is lagging.

Try the following:

  • Disable Realtime in the Show section. Overlays will only update when the camera is still.
  • Reduce the Draw Distance of the Vertex Cloud, or disable it entirely if you don't need it.
  • Reduce Max Steps in the History section to keep less undo data in memory.

Normals

Hardening edges increased my vertex count. Is that expected?

Yes, and it's intentional. Hardening an edge splits the shared vertices at that position. Each adjacent triangle gets its own copy carrying a unique outward-facing normal. That's how hard-edge shading works at the mesh data level. Smoothing does the reverse: copies are merged back into one and the count drops. Keep this in mind if vertex budget or draw cost matters for your target platform.

Some vertices are missing from the vertex cloud when I switch to the Normals brush.

Positions where every surrounding triangle is already coplanar (within about 5°) are hidden from the Normals brush cloud. Hard and smooth shading produce indistinguishable results at those positions, so the tool omits them to reduce noise. The brush, Fill Hard, and Fill Smooth on the Actions page also skip them automatically.

Fill Hard / Fill Smooth didn't affect some areas of my mesh.

Those areas are likely flat. Positions where all surrounding triangles lie within about 5° of one another have no meaningful shading difference between hard and smooth, so they're intentionally skipped. See Set Shading on the Actions page.

UV seams didn't re-weld when I used the Smooth brush.

That's by design. Vertices that lie on a UV seam carry different texture coordinates and can't share a single vertex even if their normals fully align. The Smooth brush will align the normals at those positions but won't merge the vertices. The UV seam, and any split it implies, is always preserved. This is covered in the Shared Vertices section on the Paint page.

I painted a hard edge - now how do I paint different colours on each side of it?

Switch to Vertex Paint mode on the Paint page and set Shared Verts to Split. With the vertices at that edge now separated, each triangle face has its own copy and the colour brush addresses them independently. You can paint one side, then the other, without either bleeding across.


Meshes

What is an "instanced mesh" and why does PolyPaint create one?

Unity shares mesh data between objects by default. Modifying a shared mesh would affect every object using it. When you first paint on a mesh, PolyPaint automatically creates a unique copy of it (an instanced mesh) so only that specific object is affected. The instanced mesh is saved as part of your scene.

Will my vertex colour data survive if I reimport the source mesh?

Reimporting directly will replace the mesh asset and could overwrite your painted data. Use Re-Import Mesh(es) in the Actions section instead. It pulls in the updated source file while preserving your transform, material, and vertex paint data by matching vertices by world position. Paint on vertices that have moved significantly may be distorted.

Are Re-Import Mesh(es) and Reset Mesh(es) undoable?

No. Both operations clear the undo and redo history entirely, then save the scene immediately. Re-Import Mesh(es) transfers your current vertex paint to the reimported geometry using spatial matching. Paint on vertices that have moved significantly may not transfer accurately. Reset Mesh(es) discards the instanced mesh and restores the original asset with no paint data. Save a Snapshot before using either if you want a rollback option. Both actions are documented on the Actions page.

How do I remove PolyPaint's changes from a mesh entirely?

Use Reset Mesh on the Actions page. This removes the instanced mesh and restores the original mesh asset. It can't be undone.


Object Sets

Autosave stops triggering when I deselect everything in the scene.

Autosave requires an active target. When you're using Current Selection as the source, autosave pauses when nothing is selected. Load an Object Set in the Snapshot section and set it as the source. Autosave will then continue running on that fixed set of objects regardless of your scene selection.

The Snapshot source switched to my Object Set automatically - I didn't change it.

That's intentional. When you deselect everything in the scene while an Object Set is loaded in the Snapshot section, PolyPaint automatically uses the Object Set as the source rather than leaving the tool idle. Selecting objects in the scene switches it back to Current Selection.


Snapshots

Can I apply a Snapshot to a different mesh than the one it was saved from?

Yes. Snapshots match by world position, not by mesh identity. As long as the target mesh has vertices in similar world positions to where the snapshot was recorded, the colours will transfer correctly. Use the Distance threshold to control how strict the matching is. See the Snapshots page for detail on loading and applying.

My Snapshot has fewer points than my mesh has vertices. Is that a problem?

Not necessarily. If a vertex in the target mesh has no nearby point in the Snapshot within the distance threshold, it simply won't be updated. This can be intentional, for example if you only saved a partial paint. Adjust the Distance setting on the Snapshots page if you need wider coverage.

Autosave keeps overwriting data I want to keep.

Make sure you have the correct Snapshot asset loaded before enabling Autosave. If you want to preserve a specific state, save it to a separate Snapshot asset first, then re-enable Autosave pointing at a different one. The full Autosave workflow is on the Snapshot page.


Still not solving your problem?

If your question isn't answered here, head over to the Bugs / Feedback page to report a bug, request a feature, or share your thoughts.

Instruction Booklet

In true old-school fashion, the best way to learn PolyPaint is with its included paper instruction booklet. Try not to crumple the pages.

Bugs / Feedback

Report a bug, request a feature, or share a thought about any of the tools.

Snap Verts to Grid

A MEL script that snaps selected geometry to the nearest grid position in Maya.

Maya allows you to select and snap verts to the grid, but only one at a time or as groups relative to one pivot point. This script snaps all selected verts of a mesh (or multiple) to your grid in 3D space at once. You can select entire objects, as well as individual faces, edges, or groups of verts, and snap them to the nearest grid position - on all axes at once, or just along a specific axis.

This can be useful if you're using the grid for pixel-perfect UVing, or need to precisely align many verts to a grid all at once.

Key Features

  • Snaps all selected verts to the nearest grid position in world space, independently
  • Works on entire objects, faces, edges, or individual vertex selections
  • Snap on all axes at once, or just X, Y, or Z individually
  • Grid size derived from Maya's Grid Lines Every and Subdivisions settings
  • Settings persist between sessions via Maya optionVars

Download & Setup

Installing the script and adding it to your shelf.

Installation

Download SnapVertsToGrid.zip
  1. Drag snapVertsToGrid.mel into your Maya scripts folder, e.g. Documents/Maya/2023/scripts/.
  2. Open the Script Editor in Maya via Windows > General Editors > Script Editor.
  3. In the MEL tab of the Script Editor, type source snapVertsToGrid.mel; and hit the run button (the > icon) to load the script.
  4. Still in the MEL tab, type openSnapVertsToGridWindow;, highlight it, then middle-mouse drag it onto your shelf to create a shelf button. Alternatively, just run it from the Script Editor each session.
  5. Right-click the shelf button, select Edit, and assign SnapVertsToGrid_ShelfIcon.png as the icon image.
  6. In the shelf button's Command field, include both source snapVertsToGrid.mel; and openSnapVertsToGridWindow; so the script is always sourced when you click it.
If you're getting a warning about Error: invalid syntax, double-check you're inputting in the MEL script tab and not the Python script tab.

Requirements

RequirementDetail
Maya VersionMade and tested on Maya 2023.1. May or may not work in earlier or later versions. Written in MEL rather than Python, so it should work broadly including Maya LT.
Script TypeMEL

Usage

Snapping verts to the grid.

Input your current grid settings (found in Display > Grid), select the object(s), individual face(s), vert(s), or edge(s), then hit the corresponding button to snap your verts to the nearest grid position along the specified axis.

Grid Settings

The snap interval is calculated from two values that match Maya's display grid.

FieldTypeDescription
Grid Lines EveryfloatUnits between each grid line. Match this to the "Grid lines every X units" value in Display > Grid.
SubdivisionsintSubdivisions per grid line. Match this to the "Subdivisions" value in Display > Grid. Snap interval = Grid Lines Every ÷ Subdivisions.
Settings persist between sessions via Maya optionVars - you only need to set them once per grid configuration.

Snap Buttons

ButtonDescription
XYZSnap all selected verts to the nearest grid position on all three axes at once.
XSnap only the X position of each selected vert, leaving Y and Z unchanged.
YSnap only the Y position of each selected vert, leaving X and Z unchanged.
ZSnap only the Z position of each selected vert, leaving X and Y unchanged.

FAQ

Common questions about Snap Verts to Grid.

The verts aren't snapping to the right positions.

Make sure the Grid Lines Every and Subdivisions values in the tool window exactly match what's set in Display > Grid. If those values are off, the calculated snap interval will be wrong. Settings persist between sessions via Maya optionVars, so you only need to update them when you change your grid configuration.

Does it work with my version of Maya?

The script was made and tested on Maya 2023.1. Because it is written in MEL rather than Python, it should work broadly across Maya versions, including Maya LT. Older or newer versions are untested but are unlikely to have issues.

Does the snap operation support undo?

Yes. Each snap is a single undoable action in Maya's undo queue. Press Ctrl+Z to reverse it.

Why do I have to re-source the script every Maya session?

MEL scripts are not loaded automatically on startup. The simplest fix is to include source snapVertsToGrid.mel; in your shelf button's Command field alongside openSnapVertsToGridWindow;. The script is then sourced automatically whenever you click the button. See Download & Setup for the full shelf setup steps.

Does it work on skinned meshes?

Not reliably. The script reads vertex positions in world space using pointPosition -w, which on a bound skinned mesh returns the deformed position rather than the base mesh position. Results on bound geometry may be unpredictable.


Still not solving your problem?

If your question isn't answered here, head to the Bugs / Feedback page to report a bug, request a feature, or share your thoughts.