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
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;
}
}
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;
}
}
You can’t, to my knowledge. Just type the position in.