Vertex snapping does not work properly.
Whenever i want to use the vertex snapper it always leaves a tiny gap between the two objects. Like this: http://i.imgur.com/1ghdERF.png To fix it i have to zoom in and use the snapper again. It's extremely annoying and adds a tremendous amount of tedious extra work. Any fixes?
Answer by Feelnside · Jan 23, 2018 at 01:49 PM
Looks like I found out the solution. I'm using the latest version of Unity (2017.3.0p3). In the top left corner select the new tool system (Move Rotate or Scale selected objects)
With this system I can successfully align the meshes using Vertex Snap Tool ('V' button). With simple 'Move Tool' I have the same issue as the topic starter. I hope this helps.
I'm using Unity 2018.1.9f2 and this solved my problem. Thanks.
Still broken (again) in Unity 2019.3.0f3. Your workaround with the move/rotate/scale tool helped me a lot. Thanks
Answer by andranik87 · Apr 29, 2016 at 10:24 PM
I am having the same problem here too. In some parts of the vertex snapped planes and cubes, I get gaps like these
Any one know how to fix these?
Answer by Nullmind · Jan 07, 2018 at 02:07 PM
Had the same problem.
Please, do vote this issue here so we can get a faster fix.
For now I'm using this VertexSnap script which works nicely when you press 'C' key:
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
[InitializeOnLoad]
public class MyVertexSnap {
private static MyVertexSnap instance;
private bool inSnapMode;
private bool inSnapMove;
private MeshFilter snapMesh;
private int snapVertexIndex;
private List<Transform> selectedTransforms;
static MyVertexSnap() {
if (instance == null) instance = new MyVertexSnap();
}
public static MyVertexSnap GetInstance() {
if (instance == null) instance = new MyVertexSnap();
return instance;
}
private MyVertexSnap() {
inSnapMode = false;
inSnapMove = false;
snapMesh = null;
snapVertexIndex = 0;
selectedTransforms = new List<Transform>();
SceneView.onSceneGUIDelegate += HandleOnSceneGUI;
}
~MyVertexSnap() {
SceneView.onSceneGUIDelegate -= HandleOnSceneGUI;
}
private void HandleOnSceneGUI(SceneView sv) {
Event e = Event.current;
if (e.isKey) {
if (e.type == EventType.KeyDown) {
if (e.keyCode == KeyCode.C) {
if (Tools.current == Tool.Move) {
if (!inSnapMode) {
this.FindTransforms();
this.FindVertex();
inSnapMode = true;
inSnapMove = false;
} else {
inSnapMode = true;
}
}
}
} else if (e.type == EventType.KeyUp) {
if (e.keyCode == KeyCode.C) {
if (inSnapMode) {
Undo.FlushUndoRecordObjects();
GUIUtility.hotControl = 0;
inSnapMode = false;
inSnapMove = false;
}
}
}
} else if (e.isMouse) {
if (inSnapMode) {
if (e.type == EventType.MouseMove) {
if (!inSnapMove) {
GUIUtility.hotControl = GUIUtility.GetControlID(118473327, FocusType.Passive);
this.FindVertex();
}
} else if (e.type == EventType.MouseDrag) {
GUIUtility.hotControl = GUIUtility.GetControlID(118473327, FocusType.Passive);
if (inSnapMove) this.SnapVertex();
} else if (e.type == EventType.MouseDown && e.button == 0) {
GUIUtility.hotControl = GUIUtility.GetControlID(118473327, FocusType.Passive);
if (!inSnapMove) {
this.FindVertex();
inSnapMove = true;
GameObject[] recordedObjs = new GameObject[selectedTransforms.Count];
int i = 0;
foreach (Transform t in selectedTransforms) {
recordedObjs[i] = t.gameObject;
i++;
}
Undo.RegisterCompleteObjectUndo(recordedObjs, "My Vertex Snap");
}
} else if (e.type == EventType.MouseUp && e.button == 0) {
Undo.FlushUndoRecordObjects();
GUIUtility.hotControl = 0;
selectedTransforms = new List<Transform>();
inSnapMode = false;
inSnapMove = false;
snapMesh = null;
}
}
}
}
private void FindTransforms() {
selectedTransforms = new List<Transform>(Selection.GetTransforms(SelectionMode.Unfiltered));
}
private void FindVertex() {
snapMesh = null;
snapVertexIndex = 0;
Plane cameraPlane = new Plane(
Camera.current.transform.position,
Camera.current.transform.position + Camera.current.transform.right,
Camera.current.transform.position + Camera.current.transform.up
);
Event e = Event.current;
Vector3 mousePos = new Vector3(e.mousePosition.x, Camera.current.pixelHeight - e.mousePosition.y, 0);
float searchDist = 20.0f;
foreach (Transform t in selectedTransforms) {
MeshFilter meshFilter = t.GetComponent<MeshFilter>();
if (meshFilter != null) {
Mesh mesh = meshFilter.sharedMesh;
if (mesh != null) {
Vector3[] vertices = mesh.vertices;
for (int i = 0; i < vertices.Length; i++) {
Vector3 v = vertices[i];
Vector3 worldPos = meshFilter.transform.TransformPoint(v);
if (cameraPlane.GetSide(worldPos)) {
Vector3 vertexScreenPos = Camera.current.WorldToScreenPoint(worldPos);
vertexScreenPos.z = 0;
float dist = (vertexScreenPos - mousePos).magnitude;
if (dist <= searchDist) {
searchDist = dist;
snapMesh = meshFilter;
snapVertexIndex = i;
}
}
}
}
}
}
}
private void SnapVertex() {
Plane cameraPlane = new Plane(
Camera.current.transform.position,
Camera.current.transform.position + Camera.current.transform.right,
Camera.current.transform.position + Camera.current.transform.up
);
Event e = Event.current;
Vector3 mousePos = new Vector3(e.mousePosition.x, Camera.current.pixelHeight - e.mousePosition.y, 0);
MeshFilter[] meshFilters = Object.FindObjectsOfType<MeshFilter>();
Vector3 snapPos = Vector3.zero;
bool doSnap = false;
float searchDist = 20.0f;
foreach (MeshFilter m in meshFilters) {
if (selectedTransforms.Contains(m.transform)) continue;
if (!m.gameObject.activeInHierarchy) continue;
if (m != null) {
Mesh mesh = m.sharedMesh;
if (mesh != null) {
Vector3[] vertices = mesh.vertices;
for (int i = 0; i < vertices.Length; i++) {
Vector3 v = vertices[i];
Vector3 worldPos = m.transform.TransformPoint(v);
if (cameraPlane.GetSide(worldPos)) {
Vector3 vertexScreenPos = Camera.current.WorldToScreenPoint(worldPos);
vertexScreenPos.z = 0;
float dist = (vertexScreenPos - mousePos).magnitude;
if (dist <= searchDist) {
searchDist = dist;
snapPos = worldPos;
doSnap = true;
}
}
}
}
}
}
if (doSnap) {
Vector3 originalPos = snapMesh.transform.TransformPoint(snapMesh.sharedMesh.vertices[snapVertexIndex]);
if (!originalPos.Equals(snapPos)) {
Vector3 offset = snapPos - originalPos;
foreach (Transform t in selectedTransforms) {
t.gameObject.transform.position += offset;
}
}
}
}
public void HandleOnSceneGUIDrawing() {
if (inSnapMode) {
Vector3 cameraPos = Camera.current.transform.position;
Quaternion cameraRot = Camera.current.transform.rotation;
if (snapMesh != null) {
Vector3 vertexPos = snapMesh.transform.TransformPoint(snapMesh.sharedMesh.vertices[snapVertexIndex]);
float vertexDist = (cameraPos - vertexPos).magnitude;
if (inSnapMove) Handles.color = Color.red;
else Handles.color = Color.blue;
Handles.CircleHandleCap(0, vertexPos, cameraRot, 0.015f * vertexDist, EventType.Repaint);
}
}
}
}
#endif
Also do not forget to place this VertexSnapEditor script inside your Editor folder:
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(MeshFilter))]
[CanEditMultipleObjects]
public class MyVertexSnapEditor : Editor {
public void OnSceneGUI() {
MyVertexSnap vs = MyVertexSnap.GetInstance();
vs.HandleOnSceneGUIDrawing();
}
}
Hope it helps.
I have the same issue. Tried to resolve it using your scripts: I have created two C# scripts ($$anonymous$$yVertexSnap and $$anonymous$$yVertexSnapEditor) both these scripts located inside the Editor folder (Assets/Editor) but it's not working. trying to press 'C' and nothing. Could you please clarify am I missed something?