I need it to be relative to the origin point of the world. I want to use it to snap an object to a grid.
[ExecuteInEditMode]
[CanEditMultipleObjects]
class Snap : MonoBehaviour
{
public string tagName = "Tile";
public bool alignEverything = false;
Vector3 mousePos;
Vector3 mPRange;
private void Update()
{
mousePos = ;//code to get mouse Position;
mPRange = new Vector3(((mousePos.x % 1) >= 0.5) ? 1 : -1, ((mousePos.y % 1) >= 0.5) ? 1 : -1, ((mousePos.z % 1) >= 0.5) ? 1 : -1);
//This finds all gameObjects I can move
foreach (GameObject g in Selection.GetFiltered(typeof(GameObject), SelectionMode.TopLevel | SelectionMode.Editable))
{
//These splits the GameObject into a Transform and SpriteRenderer
SpriteRenderer spr = g.GetComponent<SpriteRenderer>();
Transform t = g.transform;
//This ternary operator skips the tag check if alignEverything is set to true
if (((alignEverything && spr != null) ? (true) : (g.tag == tagName)) && Selection.Contains(g))
{
//This changes the objects transform to align to the grid in unity
g.transform.position = new Vector3( (t.position.x - (t.position.x % 1)) + (mPRange.x * spr.bounds.extents.x),
(t.position.y - (t.position.y % 1)) + (mPRange.y * spr.bounds.extents.y),
(t.position.z - (t.position.z % 1)) + (mPRange.z * spr.bounds.extents.z));
}
}
}
}
The “ExecuteInEditMode” attribute is not ment to turn a runtime script into an editor script. It’s main purpose is to get live feedback of the runtime functionality inside the editor while you’re not playing the game. For example particle systems would use this so you can actually see how it looks like while editing,
Again, it’s not ment to implement any editor extension. While it is possible to some extend it’s very limited. Also MonoBehaviour classes are runtime classes. So implementing a MonoBehaviour that is only used inside the editor makes not much sense,
You may want to implement an actual editor script. In general there are four different kinds of editor scripts:
- CustomInspector (Editor class)
- EditorWindow
- PropertyDrawer / DecoratorDrawer
- Other / general purpose
Most extensions that involve the sceneview are implemented inside custom inspectors. A custom inspecter has an OnSceneGUI callback which allows you to directly hook into the drawing and event processing of the SceneView. Though OnSceneGUI of a custom inspector is only run while an object that uses this custom inspector is currently inspected (visible in the inspector). If you deselect the object.
From all other kinds of editor scripts you can subscribe a method to the static “onSceneGUIDelegate” event of the SceneView class. SceneView.onSceneGUIDelegate += YourMethod
.
This let you handle SceneView events on a global scale.
Inside the sceneview callback you can use the usual IMGUI event system. So Event.current.mousePosition
returns the current mouse position in GUI space relative to the sceneview. If you want a world space position you usually use GUIPointToWorldRay from the HandleUtility class. To get an actual point you either use GetPoint of that ray with a certain distance, cast a ray against colliders in the scene using the Physics class or use the Plane class to define an infinite plane you can raycast against.
It’s hard to tell what exact purpose the script has and how it’s supposed to be used. You have no conditions for your “movement”, so currently everything that is selected will be affected “every frame”. The fractional mouse position will determine if the objects move in one direction or the other. At no point the objects don’t move. This seems very strange to me.
If you want to implement a special edit move / tool (like Unity’s move / rotate / view tool) you might want to create an editorwindow where you can enable / disable your tool. For this it usually makes sense to use the Tools class and set current to Tool.None while your tool is active. Though the question is how deep do you want to go into editor / tool programming? As general referemce my GUI crash course.
Btw: The attribute “CanEditMultipleObjects” only makes sense for custom inspectors. Custom inspectors without that attribute will not show up when you have multiple objects selected.
Okay thank you for the information and finally I have found the answer. I got it on this page Editor script help for finding mouse position in Scene view.
Thanks for all the assistance. I modified the code for my situation and got:
[CustomEditor(typeof(SnapToGrid))]
public class SnapToGridEditor : Editor
{
private static Vector3 position;
public static Vector3 Position
{
get { return position; }
}
static SnapToGridEditor()
{
SceneView.onSceneGUIDelegate += UpdateView;
}
private static void UpdateView(SceneView sceneView)
{
if (Event.current != null)
{
position = SceneView.currentDrawingSceneView.camera.ScreenToWorldPoint(Event.current.mousePosition);
//This makes the mouse position adjust so it is relative to the world position
position.y = -(position.y - (2 * SceneView.currentDrawingSceneView.camera.transform.position.y));
}
}
}