Search code examples
c#unity-game-engineunity3d-editor

Unity, editor-time script, On GameObject Added to Scene Event


Say you have a trivial prefab, "Box", which we'll say is nothing more than a standard meter cube.

  • 1 - The prefab Box is in your Project panel

  • 2 - Drag it to the Scene

  • 3 - Obviously it now appears in the Hierarchy panel also, and probably selected and shown in Inspector

To be clear, game is NOT Play when you do this, you're only in ordinary Editor mode.

Is it possible to make a script (an "Editor script"?) so that,

  • when you do "1" and "2" above, (again this is in Editor mode, not during a game)

  • when 3 happens, we can affect the new Box item in the scene

  • So, simple example: we will set the Z position to "2" always, no matter where you drop it.

In short: Editor code so that every time you drag a prefab P to the scene, it sets the position z to 2.0.

Is this possible in Unity? I know nothing of "editor scripts".

It seems very obvious this should be possible.


Solution

  • You can add a custom window editor which implements OnHierarchyChange to handle all the changes in the hierarchy window. This script must be inside the Editor folder. To make it work automatically make sure you have this window opened first.

    using System.Linq;
    using UnityEditor;
    using UnityEngine;
    
    public class HierarchyMonitorWindow : EditorWindow
    {
        [MenuItem("Window/Hierarchy Monitor")]
        static void CreateWindow()
        {
            EditorWindow.GetWindow<HierarchyMonitorWindow>();
        }
    
        void OnHierarchyChange()
        {
            var addedObjects = Resources.FindObjectsOfTypeAll<MyScript>()
                                        .Where(x => x.isAdded < 2);
    
            foreach (var item in addedObjects)
            {
                //if (item.isAdded == 0) early setup
                
                if (item.isAdded == 1) {
                    
                    // do setup here,
                    // will happen just after user releases mouse
                    // will only happen once
                    Vector3 p = transform.position;
                    item.transform.position = new Vector3(p.x, 2f, p.z);
                }
    
                // finish with this:
                item.isAdded++;
            }
        }
    }
    

    I attached the following script to the box:

    public class MyScript : MonoBehaviour {
        public int isAdded { get; set; }
    }
    

    Note that OnHierarchyChange is called twice (once when you start dragging the box onto the scene, and once when you release the mouse button) so isAdded is defined as an int to enable its comparison with 2. So you can also have initialization logic when x.isAdded < 1