I’ve been learning Unity for a few weeks now, and one thing in particular bugs me. It’s difficult to position objects in the scene view. Yet it is insanely easy to fly around in the scene view with move tool active.
It would be SUPER convenient to just move the view in scene view to both the position and orientation I want a game object to be in, and then assign that position and orientation to the game object. Is there no way to do that? If not, why not? Am I missing something? After just 3 weeks, it seems this would be an obvious way for Unity to allow game objects to be positioned. Just fly to the spot. Drop it. Then tweak.
Perhaps even better, have the game object you want to place hover a certain distance in front of you, then fly it to where you want it and drop.
Instead, I have to place an object, and it just kind of goes somewhere random in the scene. And then I have to drag it around by the 3 handles, constantly repositioning my view to keep my mind properly oriented to where it actually is in the 3D space. Then I have to rotate it. Move it some more. Rotate it some more. It takes a long time. On top of that, I can’t just set the position to where my view is manually, because it won’t show me what my view position is.
More than just complaining, I’m just looking for any tips or to hear how you all position objects around the scene. Maybe there’s an easier way.
If you want to move it with the camera, you can do that by making a simple editor script.
It should just be a matter of getting the currently selected object, and placing it x forward from the current SceneView.
I would recommend just getting used to the normal way, I can’t think of any software that doesn’t use the 3 axis to move things.
Thanks. I do remember briefly seeing something about an editor script a week or so ago. I just thought it unlikely you could actually mod the editor. But maybe it was a thing after all. I’ll look into that. If there isn’t a huge barrier to making a script that interacts with the editor view, I’ll work on that. And share it. I bet a lot of people will like it. It would make life SO much easier.
Here’s a first stab at an editor script to move objects. It adds a Tow Object toggle that allows you to move an object, or tow it, by just flying around with it. Toggle back off to stop towing. But it has a few potential issues, which I’ll mention at the end. But it’s a starting point for anyone interested in such behavior:
[CustomEditor(typeof(GameObject))]
public class TowEditorControl : Editor
{
private bool towing = false;
private GameObject gameObject;
private float distance;
public void OnSceneGUI()
{
Handles.BeginGUI();
GUILayout.Space(10);
GUIStyle style = new GUIStyle();
style.padding = new RectOffset(60, 60, 0, 0);
GUILayout.BeginHorizontal(style);
if (GUILayout.Toggle(towing, "Tow Object"))
{
this.gameObject = Selection.activeGameObject;
if (this.gameObject != null)
{
Vector3 viewPosition = SceneView.currentDrawingSceneView.camera.transform.position;
if (!towing)
{
towing = true;
this.distance = (this.gameObject.transform.position - viewPosition).magnitude;
}
GUILayout.Label("Towing " + this.gameObject.name);
Vector3 viewUnitForward = SceneView.currentDrawingSceneView.camera.transform.forward;
this.gameObject.transform.position = viewPosition + viewUnitForward * this.distance;
} else
{
// this shouldn't happen, but just in case...
GUILayout.Label("A game object must be selected before activating tow.");
}
} else
{
towing = false;
}
GUILayout.EndHorizontal();
Handles.EndGUI();
}
}
Drop this in folder Assets/Editor/ and it should become live.
Issues:
As is, this script, when Tow toggle is activated with object selected, will move the selected object directly ahead of you on activation (but at the same distance as when Tow was activated). I did this for simplicity. But it would be better to keep it’s position the same relative to the view, so object doesn’t move when Tow is first engaged, and stays at the same relative viewing angle as you move around. But that’s complicated, so I haven’t tried to do it yet. Another half way option would be just to turn the sceneview towards the object first so object won’t move on Tow activation. But I couldn’t figure out how to do that; you can’t control the sceneview camera directly, and the sceneview methods for LookAt and Frame all move the position of the view, which I don’t want. So it is what is for now.
I spent very little time on the layout of the toggle and tow label. That could be greatly improved.
I’m not sure if it’s proper to move game objects from within the OnSceneGUI method. But it seems to work.
Ad additional tip, since this is a beginners forum. In case you haven’t already figured it out, with Move Tool selected in scene view, you can fly around by holding down the right mouse button. Then you can turn with the mouse and move with WASD just like in a game. Once I figured that out, I stopped using View Tool and just stay in Move Tool mode most of the time.
FYI: I HIGHLY recommend if you use this you also come up with a way to exclude certain game objects from being towable. You could add some sort of NoTow dummy component that the editor script looks for, or maybe just exclude certain tags and tag your game objects accordingly. For example, you will likely want to exclude Terrain.
On my script, I also added a couple of additional labels to show camera position and object position, and switched the basic layout to Vertical. There are lots of things you could do with this script to enhance it further.
WARNING! I found a serious bug with this script. It breaks adding prefabs to the scene by dragging them into the scene. I don’t know how to fix this yet. I’ll post an update when I figure it out.
I think what is needed to fix this is to use an EditorWindow and not an Editor. But I have another problem. I put the script shown below in two different projects. It works in one but not the other. Both only have the one (exact same) script in the Assets/Editor folder. I can’t explain this, but it’s yet another frustration, because I really want it in the project it’s not working in.
Note: This one doesn’t include the tow ability, it just prints camera position on screen. I was trying to keep it simple for debugging until it was working.
using UnityEngine;
using UnityEditor;
public class TowEditorWindow : EditorWindow
{
private void OnEnable()
{
SceneView.duringSceneGui -= OnSceneGUI;
SceneView.duringSceneGui += OnSceneGUI;
}
private void OnDestroy()
{
SceneView.duringSceneGui -= OnSceneGUI;
}
public void OnSceneGUI(SceneView sceneView)
{
Handles.BeginGUI();
GUILayout.Space(10);
GUIStyle style = new GUIStyle();
style.padding = new RectOffset(60, 0, 0, 0);
GUILayout.BeginVertical(style);
Vector3 viewPosition = sceneView.camera.transform.position;
GUILayout.Label("Camera Position: " + viewPosition.ToString());
GUILayout.EndVertical();
Handles.EndGUI();
}
}
Thank you for the reply. That maybe gives me a clue. Perhaps I still don’t have everything I need. But then, why does it work in my first project? Crazy. I’ll look into if I have to open it somehow. Or activate it. It’s not a window, it is just supposed to do stuff in the scene display.
So I added this to the class:
[MenuItem("Window/Tow Tool")]
public static void ShowTowTool()
{
EditorWindow.GetWindow<TowEditorWindow>();
}
And now we are getting somewhere, but it is still not what is wanted. This creates a new window. The label indeed appears on the scene, but the separately launched window is not wanted. I just want to print stuff to the scene.
So an Editor isn’t quite what I want, because it interferes with normal editing. And an EditorWindow might sort of work, but can I activate it without having an actual window that opens?
Do you still have the previous iteration of the code in your project? Mind you if it was a custom editor, and then was turned in an editor window, the in-memory instance is still hanging around potentially. If you close and re-open the first project, I imagine it will stop working.
Nonetheless EditorWindow’s are the windows you open in the project, like the inspector, heirarchy, scene view, etc. They’re all editor windows. They don’t do anything if they’re not open.
If you don’t want a window to be open, but also don’t want it to be part of the inspector of a component, then you should look at a custom overlay: Unity - Manual: Create your own overlay
Thanks. I somehow missed it in the docs and was trying to piece it together from other sources. I’ve got an updated solution now that may still have problems but I think it’s a lot closer to what it should be. I used an Overlay. It now has not only tow capability but forbids some objects from being towed by tag and also shows camera and towed object positions. Here’s the latest code: