- Home /
Snap to starting position?
Although I know how to snap objects' position when moving them in the Scene (holding down Cmd/Cntrl), unfortunately they snap relative to their starting position, e.g. if x = 1.234, then snap-moving 1m will move it to 2.234. How do you snap them to whole numbers without manually typing in an integer position? I'm surprised this isn't the default behaviour. When you initially drag a piece in to the scene it invariably goes to a non-integer position, which would mean setting its integer position manually every time.
Thanks
Answer by Rod-Green · Dec 30, 2011 at 10:09 PM
Or as an editor tool
using UnityEngine;
using UnityEditor;
public class SnapperTool : ScriptableObject
{
public Vector3 m_snapValues = Vector3.one;
static SnapperTool m_instance;
static Vector3 GetSnapValues()
{
if(m_instance == null)
{
m_instance = GetInstance();
}
return m_instance.m_snapValues;
}
static SnapperTool GetInstance()
{
if(m_instance != null)
return m_instance;
SnapperTool[] sceneSnappers = (SnapperTool[])FindSceneObjectsOfType(typeof(SnapperTool));
SnapperTool sceneSnapper = null;
if(sceneSnappers.Length != 0)
sceneSnapper = sceneSnappers[0];
if(sceneSnapper == null)
{
sceneSnapper = ScriptableObject.CreateInstance<SnapperTool>();
sceneSnapper.hideFlags = HideFlags.dontSave;
}
m_instance = sceneSnapper;
return m_instance;
}
[MenuItem ("Tools/Snapper Settings")]
static void SnapperSettings ()
{
UnityEditor.Selection.objects = new Object[] { GetInstance() };
}
[MenuItem ("Tools/Snap")]
static void DoSnapSelection ()
{
if(Selection.gameObjects == null || Selection.gameObjects.Length == 0)
return;
foreach(GameObject eachGO in Selection.gameObjects)
{
SnapGameObject(eachGO);
}
}
static void SnapGameObject(GameObject p_go)
{
Vector3 snapValues = GetSnapValues();
Vector3 curPos = p_go.transform.localPosition;
curPos.x = Snap(curPos.x, snapValues.x);
curPos.y = Snap(curPos.y, snapValues.y);
curPos.z = Snap(curPos.z, snapValues.z);
p_go.transform.localPosition = curPos;
}
static float Snap(float p_value, float p_snap)
{
if(p_snap <= 0.0f)
return p_value;
return (float)Mathf.RoundToInt(p_value / p_snap) * p_snap;
}
}
Wow, Rod, thanks so much, a great solution and so much quicker than having to type in values or open the Unity snap settings prefs. I added a key shortcut to the "Tools/Snap &s" also. :) :)
Actually one issue with this is it might save the SO with the scene... Let me fix
Answer by Rod-Green · Dec 30, 2011 at 09:52 PM
As a mono you could do something like
using UnityEngine;
[ExecuteInEditMode]
public class Snapper : MonoBehaviour
{
public Vector3 m_snapValues = Vector3.one;
float Snap(float p_value, float p_snap)
{
if(p_snap <= 0.0f)
return p_value;
return (float)Mathf.RoundToInt(p_value / p_snap) * p_snap;
}
void Update()
{
if(Application.isPlaying)
return;
Vector3 curPos = transform.localPosition;
curPos.x = Snap(curPos.x, m_snapValues.x);
curPos.y = Snap(curPos.y, m_snapValues.y);
curPos.z = Snap(curPos.z, m_snapValues.z);
transform.localPosition = curPos;
}
}
Answer by macweirdo · Dec 30, 2011 at 05:00 PM
You can't, to my knowledge. Just type the position in.
Your answer
Follow this Question
Related Questions
Editor Handles Vertex Snap not working on script's object. 0 Answers
Camera rotation around player while following. 6 Answers
Snap object to grid with offset? 1 Answer
Instantiated prefab position 5 Answers
Deviating from path while falling down. 3 Answers