Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
8
Question by spenick · Jul 26, 2011 at 10:54 PM · gridtogglesnap

Is there a toggle for snap to grid?

Currently the only way I know of to use Snap to Grid feature when moving objects is to hold down the "Command" (or "Control" for PC).

Is there anywhere in the editor you can toggle this option so you don't have to hold down a button all the time for object placement?

If there is not a toggle option some where, what would be the best way to go about adding this feature to the editor?

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image BradOZman · Feb 27 at 02:44 AM 0
Share

If the grid is visible it should be on. I think it's quite stupid that the toggle only affects it being visible or not. Turning on/off should also make it useful.

10 Replies

· Add your reply
  • Sort: 
avatar image
20
Best Answer

Answer by karl_ · Jul 27, 2011 at 02:15 AM

I scoured the docs, but it doesn't look like this is something configurable. Instead, I wrote this little editor script that does essentially the same thing. (Note- It will always round down, but this could be pretty easily fixed)

Place this script in a folder named "Editor", and hit CTRL-L or open Edit/AutoSnap to access the menu.

@script ExecuteInEditMode()

class autoSnap extends EditorWindow { var prevPosition : Vector3; var doSnap : boolean = false; var snapValue: float = 1; @MenuItem("Edit/Auto Snap %_l")

 static function Init () 
 {
     var window : autoSnap = EditorWindow.GetWindow(autoSnap);
 }

 function OnGUI()
 {
     doSnap = EditorGUILayout.Toggle("Autosnap", doSnap);
     snapValue = EditorGUILayout.FloatField("Snap Value", snapValue);
 }

 function Update()
 {
     if(Selection.transforms.Length > 0 && !EditorApplication.isPlaying)
     if(doSnap && Selection.transforms[0].position != prevPosition)
         snap();
 }

 function snap()
 {
     try
     {
         for(i = 0; i < Selection.transforms.Length; i++)
         {               
             var t : Vector3 = Selection.transforms[i].transform.position;       
             t.x = round(t.x);
             t.y = round(t.y);
             t.z = round(t.z);

             Selection.transforms[i].transform.position = t;
         }
         prevPosition = Selection.transforms[0].position;
     }
     catch(e)
     {
         // Nothing to move.
         Debug.LogError("Nothing to move.  " + e);
     }
 }

 function round(input : float)
 {
     var snappedValue : float;

     snappedValue = snapValue * Mathf.Round((input / snapValue));

     return(snappedValue);
 }

}

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image yatayata · Sep 06, 2011 at 02:30 AM 0
Share

is this a C# script? i get this error:

 NullReferenceException: Object reference not set to an instance of an object
 UnityEditor.EditorWindow.GetWindow (System.Type t, Boolean utility, System.String title, Boolean focus)
 UnityEditor.EditorWindow.GetWindow (System.Type t)
 autoSnap.Init () (at /users/dc/Dropbox/travagent/un1/app1/Assets/Editor/GridSnap.js:12)

which is this line:

 var window : autoSnap = EditorWindow.GetWindow(autoSnap);

window var is also flagged as not used...

avatar image karl_ · Sep 06, 2011 at 02:53 AM 0
Share

This is written in JS

avatar image schetty karl_ · Jun 21, 2016 at 09:24 AM 0
Share

can v use this at rutime?

avatar image Essential · Feb 28, 2012 at 02:29 AM 0
Share

Cool, great script, thanks!

Just a note for others, it seems that the window needs to stay open for the autosnapping to function. But you can just leave it in the background behind other windows.

avatar image mweldon · Apr 15, 2012 at 09:14 PM 2
Share

You can also dock it somewhere to keep it open and out of the way.

avatar image
36

Answer by DannyB · Sep 10, 2013 at 03:24 PM

Since this is the first result for "unity snap to grid" in Google, I figured we should also have an updated answer here for newer Unity versions and for the benefit of other people landing on this page.

  1. Press control while dragging

  2. Edit snap settings in Edit > Snap Settings...

  3. More info in this doc page

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image the_real_ijed · Dec 16, 2013 at 03:41 PM 0
Share

Great stuff, thanks for this.

Unity not having proper grid setup out of the box is very strange.

Personally I consider anything being off grid as a bug.

avatar image WizardMatthew · Aug 31, 2015 at 02:38 PM 0
Share

Thanks for adding this note. Logged in so I could upvote this second comment and let it be first soon.

avatar image
19

Answer by mweldon · Apr 15, 2012 at 09:13 PM

Here is the C# version.

 using UnityEngine;
 using UnityEditor;
 
 public class AutoSnap : EditorWindow
 {
     private Vector3 prevPosition;
     private bool doSnap = true;
     private float snapValue = 1;
 
     [MenuItem( "Edit/Auto Snap %_l" )]
 
     static void Init()
     {
         var window = (AutoSnap)EditorWindow.GetWindow( typeof( AutoSnap ) );
         window.maxSize = new Vector2( 200, 100 );
     }
 
     public void OnGUI()
     {
         doSnap = EditorGUILayout.Toggle( "Auto Snap", doSnap );
         snapValue = EditorGUILayout.FloatField( "Snap Value", snapValue );
     }
 
     public void Update()
     {
         if ( doSnap
             && !EditorApplication.isPlaying
             && Selection.transforms.Length > 0
             && Selection.transforms[0].position != prevPosition )
         {
             Snap();
             prevPosition = Selection.transforms[0].position;
         }
     }
 
     private void Snap()
     {
         foreach ( var transform in Selection.transforms )
         {
             var t = transform.transform.position;
             t.x = Round( t.x );
             t.y = Round( t.y );
             t.z = Round( t.z );
             transform.transform.position = t;
         }
     }
 
     private float Round( float input )
     {
         return snapValue * Mathf.Round( ( input / snapValue ) );
     }
 }
Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Lukas-Barbarossa · Jul 18, 2012 at 05:05 PM 0
Share

Awesome job karl_ and mweldon. Above and beyond. Very generous use of your time.

avatar image DatBear · Mar 07, 2014 at 07:24 PM 1
Share

If you add

void OnEnable() { EditorApplication.update += Update; }

the script will keep running even when it is in a hidden tab, or closed, which will make it truly a toggle. You'll have to open it again to disable the snapping to grid if you close it.

avatar image bobmoff DatBear · Mar 12, 2016 at 07:33 PM 0
Share

thank you!

avatar image
5

Answer by imekon · Dec 19, 2015 at 03:00 PM

I found the scripts in here would fail once the auto snap window was closed. It has to do with the update event. I've also added snap to scaling, so here's my version:

  using UnityEngine; 
  using UnityEditor;
  
  public class AutoSnap : EditorWindow
  {
     private Vector3 prevPosition;
     private Vector3 prevScale;
     private Vector3 prevRotation;
     
     // These need to be static because the auto snap window is
     // recreated when opened from the menu
     private static bool doSnap = false;
     private static bool doScaleSnap = false;
     private static bool doRotateSnap = false;
     private static float snapValueX = 1;
     private static float snapValueY = 1;
     private static float snapValueZ = 1;
     private static float snapRotateValue = 1;
     
     // We need to remember the window doing the snap updates
     // so it will do it when the window is closed
     private static AutoSnap updateWindow = null;
  
     private const string doSnapKey            = "AutoSnap_doSnapKey";
     private const string doScaleSnapKey        = "AutoSmap_doScaleSnapKey";
     private const string doRotateSnapKey      = "AutoSnap_doRotateSnapKey";
     private const string snapValueXKey        = "AutoSnap_snapValueXKey";
     private const string snapValueYKey        = "AutoSnap_snapValueYKey";
     private const string snapValueZKey        = "AutoSnap_snapValueZKey";
     private const string snapRotateValueKey = "AutoSnap_snapRotateValueKey";
  
     [MenuItem( "Edit/Auto Snap %_l" )]
       
     static void Init()
     {
         // Debug.Log("AutoSnap: Init");
           
         AutoSnap window = (AutoSnap)EditorWindow.GetWindow( typeof( AutoSnap ) );
         window.maxSize = new Vector2( 200, 125 );
         window.Show();
     }
       
     public void OnGUI()
     {
         // Debug.Log("AutoSnap: OnGUI");
           
         doSnap = EditorGUILayout.Toggle( "Auto Snap", doSnap );
         doScaleSnap = EditorGUILayout.Toggle( "Auto Snap Scale", doScaleSnap);
         doRotateSnap = EditorGUILayout.Toggle ("Auto Snap Rotation", doRotateSnap);
 
         snapValueX = EditorGUILayout.FloatField( "Snap X Value", snapValueX );
         snapValueY = EditorGUILayout.FloatField( "Snap Y Value", snapValueY );
         snapValueZ = EditorGUILayout.FloatField( "Snap Z Value", snapValueZ );
 
         snapRotateValue = EditorGUILayout.FloatField ("Rotation Snap Value", snapRotateValue);
     }
       
     public void Update()
     {
         if (!EditorApplication.isPlaying && Selection.transforms.Length > 0)
         {
             // Debug.Log("AutoSnap: Update");
         
             if ( doSnap                
                 && Selection.transforms[0].position != prevPosition )
             {
                 Snap();
                 prevPosition = Selection.transforms[0].position;
             }
             
             if ( doScaleSnap
                 && Selection.transforms[0].localScale != prevScale)
             {
                 ScaleSnap();
                 prevScale = Selection.transforms[0].localScale;
             }
   
             if ( doRotateSnap
                 && Selection.transforms[0].eulerAngles != prevRotation )
             {
                 RotateSnap();
                 prevRotation = Selection.transforms[0].eulerAngles;
             }
         }
     }
   
     private void Snap()
     {
         // Debug.Log("AutoSnap: Snap");
           
         foreach ( var transform in Selection.transforms )
         {
             var t = transform.transform.position;
             t.x = RoundX( t.x );
             t.y = RoundY( t.y );
             t.z = RoundZ( t.z );
             transform.transform.position = t;
         }
     }
       
     private void ScaleSnap()
     {
         // Debug.Log("AutoSnap: ScaleSnap");
           
         foreach ( var transform in Selection.transforms )
         {
             var s = transform.transform.localScale;
             s.x = ScaleRoundX(s.x);
             s.y = ScaleRoundY(s.y);
             s.z = ScaleRoundZ(s.z);
             transform.transform.localScale = s;
         }
     }
   
     private void RotateSnap()
     {
         // Debug.Log("AutoSnap: RotateSnap");
           
         foreach (var transform in Selection.transforms)
         {
             var r = transform.transform.eulerAngles;
             r.x = RotateRound (r.x);
             r.y = RotateRound (r.y);
             r.z = RotateRound (r.z);
             transform.transform.eulerAngles = r;
         }
     }
       
     private float RoundX( float input )
     {
         return snapValueX * Mathf.Round( ( input / snapValueX ) );
     }
       
     private float RoundY( float input )
     {
         return snapValueY * Mathf.Round( ( input / snapValueY ) );
     }
       
     private float RoundZ( float input )
     {
         return snapValueZ * Mathf.Round( ( input / snapValueZ ) );
     }
     
     private float ScaleRoundX( float input )
     {
         return snapValueX * Mathf.Round( ( input / snapValueX ) );
     }
       
     private float ScaleRoundY( float input )
     {
         return snapValueY * Mathf.Round( ( input / snapValueY ) );
     }
       
     private float ScaleRoundZ( float input )
     {
         return snapValueZ * Mathf.Round( ( input / snapValueZ ) );
     }
   
     private float RotateRound( float input )
     {
         return snapRotateValue * Mathf.Round( ( input / snapRotateValue ) );
     }
   
     public void OnEnable() 
     {
         // Debug.Log("AutoSnap: OnEnable");
           
         if (EditorPrefs.HasKey(doSnapKey)) 
         {
              doSnap = EditorPrefs.GetBool(doSnapKey);
         }
         
         if (EditorPrefs.HasKey(doScaleSnapKey))
         {
             doScaleSnap = EditorPrefs.GetBool(doScaleSnapKey);
         }
         
         if (EditorPrefs.HasKey(doRotateSnapKey)) 
         {
              doRotateSnap = EditorPrefs.GetBool(doRotateSnapKey);
         }
         
         if (EditorPrefs.HasKey(snapValueXKey)) 
         {
              snapValueX = EditorPrefs.GetFloat(snapValueXKey);
         }
         
         if (EditorPrefs.HasKey(snapValueYKey)) 
         {
              snapValueY = EditorPrefs.GetFloat(snapValueYKey);
         }
         
         if (EditorPrefs.HasKey(snapValueZKey)) 
         {
              snapValueZ = EditorPrefs.GetFloat(snapValueZKey);
         }
         
         if (EditorPrefs.HasKey(snapRotateValueKey)) 
         {
              snapRotateValue = EditorPrefs.GetFloat(snapRotateValueKey);
         }
         
         // Here, if a previous auto snap window was doing updates,
         // remove it
         if (updateWindow != null)
         {
             EditorApplication.update -= updateWindow.Update;
         }
  
         // Now make this window handle the updates
         EditorApplication.update += Update;
     }
  
     public void OnDisable()
     {
         Debug.Log("AutoSnap: OnDisable");
           
         EditorPrefs.SetBool(doSnapKey, doSnap);
         EditorPrefs.SetBool(doScaleSnapKey, doScaleSnap);
         EditorPrefs.SetBool(doRotateSnapKey, doRotateSnap);
         EditorPrefs.SetFloat(snapValueXKey, snapValueX);
         EditorPrefs.SetFloat(snapValueYKey, snapValueY);
         EditorPrefs.SetFloat(snapValueZKey, snapValueZ);
         EditorPrefs.SetFloat(snapRotateValueKey, snapRotateValue);
         
         // Remember we're doing the updates
         updateWindow = this;
         
         // Normally you'd remove the window, however we don't
         // as we want the snapping to continue when this window is closed
         //EditorApplication.update -= Update;
     }
 }
  
Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image NintendoMaster00 · Jan 10, 2016 at 02:25 AM 0
Share

Thank you this version works awesome!

avatar image Erdrako · Jul 02, 2016 at 12:07 PM 0
Share

10/10! works perfect for me!

avatar image Zamaroht · Aug 17, 2016 at 02:51 PM 0
Share

Excellent! But the rotation snap is not working correctly for me :(

avatar image soldierfortune · Feb 04, 2017 at 05:38 PM 0
Share

Yes works great except for rotation! EDIT I'm a dummy lol. You have to turn it on for it to work. Works Great!

avatar image Zyblade · Jan 13, 2020 at 12:42 AM 0
Share

Still awesome! I needed that for axis independent grid snapping. Pro grids sadly doesn't support that <.< Thanks for adding this extended version.

avatar image
4

Answer by XOR-Gaming · May 29, 2015 at 09:12 AM

Hi all,

Here is AutoSnap modified to save your previous Snap Values (C#):

 using UnityEngine; using UnityEditor;
 
  public class AutoSnap : EditorWindow
  {
      private Vector3 prevPosition;
      private Vector3 prevRotation;
      private bool doSnap = true;
      private bool doRotateSnap = true;
      private float snapValueX = 1;
      private float snapValueY = 1;
      private float snapValueZ = 1;
      private float snapRotateValue = 1;
 
     private const string doSnapKey        = "AutoSnap_doSnapKey";
     private const string doRotateSnapKey  = "AutoSnap_doRotateSnapKey";
     private const string snapValueXKey    = "AutoSnap_snapValueXKey";
     private const string snapValueYKey    = "AutoSnap_snapValueYKey";
     private const string snapValueZKey    = "AutoSnap_snapValueZKey";
     private const string snapRotateValueKey = "AutoSnap_snapRotateValueKey";
 
      [MenuItem( "Edit/Auto Snap %_l" )]
      
      static void Init()
      {
          AutoSnap window = (AutoSnap)EditorWindow.GetWindow( typeof( AutoSnap ) );
          window.maxSize = new Vector2( 200, 125 );
      }
      
      public void OnGUI()
      {
          doSnap = EditorGUILayout.Toggle( "Auto Snap", doSnap );
          doRotateSnap = EditorGUILayout.Toggle ("Auto Snap Rotation", doRotateSnap);
          snapValueX = EditorGUILayout.FloatField( "Snap X Value", snapValueX );
          snapValueY = EditorGUILayout.FloatField( "Snap Y Value", snapValueY );
          snapValueZ = EditorGUILayout.FloatField( "Snap Z Value", snapValueZ );
          snapRotateValue = EditorGUILayout.FloatField ("Rotation Snap Value", snapRotateValue);
      }
      
      public void Update()
      {
          if ( doSnap
              && !EditorApplication.isPlaying
              && Selection.transforms.Length > 0
              && Selection.transforms[0].position != prevPosition )
          {
              Snap();
              prevPosition = Selection.transforms[0].position;
          }
  
          if ( doRotateSnap
              && !EditorApplication.isPlaying
              && Selection.transforms.Length > 0
              && Selection.transforms[0].eulerAngles != prevRotation )
          {
              RotateSnap();
              prevRotation = Selection.transforms[0].eulerAngles;
              //Debug.Log("Value of rotation " + Selection.transforms[0].rotation);
              //Debug.Log ("Value of old Rotation " + prevRotation);
          }
      }
  
      private void Snap()
      {
          foreach ( var transform in Selection.transforms )
          {
              var t = transform.transform.position;
              t.x = RoundX( t.x );
              t.y = RoundY( t.y );
              t.z = RoundZ( t.z );
              transform.transform.position = t;
          }
      }
  
      private void RotateSnap()
      {
          foreach (var transform in Selection.transforms)
          {
              var r = transform.transform.eulerAngles;
              r.x = RotRound (r.x);
              r.y = RotRound (r.y);
              r.z = RotRound (r.z);
              transform.transform.eulerAngles = r;
          }
      }
      
      private float RoundX( float input )
      {
          return snapValueX * Mathf.Round( ( input / snapValueX ) );
      }
      private float RoundY( float input )
      {
          return snapValueY * Mathf.Round( ( input / snapValueY ) );
      }
      private float RoundZ( float input )
      {
          return snapValueZ * Mathf.Round( ( input / snapValueZ ) );
      }
  
      private float RotRound( float input )
      {
          //Debug.Log ("The division is: " + (input / snapRotateValue ) );
          //Debug.Log ("The rounding is: " + Mathf.Round( ( input / snapRotateValue ) ) );
          //Debug.Log ("The return is: " + (snapRotateValue * Mathf.Round( ( input / snapRotateValue ) )));
          return snapRotateValue * Mathf.Round( ( input / snapRotateValue ) );
      }
  
      public void OnEnable() {
         if (EditorPrefs.HasKey(doSnapKey)) {
             doSnap = EditorPrefs.GetBool(doSnapKey);
         }
         if (EditorPrefs.HasKey(doRotateSnapKey)) {
             doRotateSnap = EditorPrefs.GetBool(doRotateSnapKey);
         }
         if (EditorPrefs.HasKey(snapValueXKey)) {
             snapValueX = EditorPrefs.GetFloat(snapValueXKey);
         }
         if (EditorPrefs.HasKey(snapValueYKey)) {
             snapValueY = EditorPrefs.GetFloat(snapValueYKey);
         }
         if (EditorPrefs.HasKey(snapValueZKey)) {
             snapValueZ = EditorPrefs.GetFloat(snapValueZKey);
         }
         if (EditorPrefs.HasKey(snapRotateValueKey)) {
             snapRotateValue = EditorPrefs.GetFloat(snapRotateValueKey);
         }
 
         EditorApplication.update += Update;
      }
 
      public void OnDisable() {
         EditorPrefs.SetBool(doSnapKey, doSnap);
         EditorPrefs.SetBool(doRotateSnapKey, doRotateSnap);
         EditorPrefs.SetFloat(snapValueXKey, snapValueX);
         EditorPrefs.SetFloat(snapValueYKey, snapValueY);
         EditorPrefs.SetFloat(snapValueZKey, snapValueZ);
         EditorPrefs.SetFloat(snapRotateValueKey, snapRotateValue);
      }
  }
 
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
  • 1
  • 2
  • ›

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

27 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Round position 1 Answer

Orthogonal View: snapping objects to grid at runtime 1 Answer

How can I snap to hex tile centers in world x,z coords? 1 Answer

Gameobject follow mouse on center 1 Answer

Snap object to grid with offset? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges