// Iterates over selected objects, finds nearest vertex or pivot and sets Tools.handleOffset accordingly private static void UpdateVertexSnappingOffset() { Event evt = Event.current; // If pressing ctrl/cmd key while using vertex snapping, // then the pivot should be used to snap on vertices if (EditorGUI.actionKey && !evt.shift) { Tools.InvalidateHandlePosition(); Tools.handleOffset = Vector3.zero; return; } Tools.vertexDragging = true; Vector3 nearestVertex; Transform[] selection = Selection.GetTransforms(SelectionMode.Deep | SelectionMode.ExcludePrefab | SelectionMode.Editable); // Make sure we're not ignoring any objects, that other handles may have set to ignore and forgot to reset. HandleUtility.ignoreRaySnapObjects = null; Vector3 nearestPivot = FindNearestPivot(selection, evt.mousePosition); bool foundVertex = HandleUtility.FindNearestVertex(evt.mousePosition, selection, out nearestVertex); Vector3 near; // Is nearest vertex closer than nearest pivot? float distanceToNearestVertex = (HandleUtility.WorldToGUIPoint(nearestVertex) - evt.mousePosition).magnitude; float distanceToNearestPivot = (HandleUtility.WorldToGUIPoint(nearestPivot) - evt.mousePosition).magnitude; if (foundVertex && (distanceToNearestVertex < distanceToNearestPivot)) { near = nearestVertex; } else { near = nearestPivot; } // Important to reset handleOffset before querying handlePosition, // since handlePosition depends on handleOffset. Tools.InvalidateHandlePosition(); Tools.handleOffset = Vector3.zero; Tools.handleOffset = near - Tools.handlePosition; }