Click and drag component order (Feature Request)

To the Unity Team…

Can we PUHLEEeeeaaaasssse have an editor feature that allows us to click and drag components to reorder them, instead of having to move up or down one level at a time through the context menu? I’ve been waiting for this for years, assuming that it was eventually going to happen and it never has. Using the context menu is tedious as hell if you have a lot of components on an object. Hell, it’s tedious even if you only have two components.

5 Likes

What’s the use case? Component order on a GameObject is pure cosmetics.

In PlatformerPRO I use it to control the priority between the different movements. Its much easier to visualise than (e.g.) requiring users to type in a priority number.

EDIT: I do have a patch with my own movement order editor in case unity ever decides to change how GetComponents/InChildren works, but for now (and since v4) this allows a very natural way for a user to order many components.

There are other use cases, such as stacking image effects on a camera where the order can significantly alter the information available to subsequent effects thus changing the output of the final image.

Besides, cosmetics (or some would say organization) should not be discounted as frivolous.

1 Like

Not exactly what was requested, but this guy has a script to move a component to the top… should be able to extend it easily to meet most needs (reorder in a preferred order when the component exists on the game object, etc.).

Though drag and drop would definitely be preferable.

Not always, some image effects act different when they are above or below specifics ones.
(I can’t say right off the top of my head right now). But it’s very much true that that can definitely happen.

In which case I withdraw my comments. If this stuff matters it should totally be included in the default editor behavior.

I didn’t realize it for awhile. Until one dark day ( technically Unity went dark) lol.
I was adding effects, and gameview just went black, I couldn’t figure out why, then I moved one of the effects up one by one until it stopped. Fixed it. PLUS +++++ If certain ones are above the other it gives even better results than just throwing them on there (it’s a lot of trail and error lol).

1 Like

Oh please yes, i’ve been waiting for this tool for years. Very usefull for components/effect chaining . .

1 Like

I suspect the order in which Start, Awake, Update, etc, is called is probably in the same order those components are displayed. It would probably be pretty easy to test. I don’t think Unity ever intended that developers depend on that order however. They probably just call those methods linearly in the order of the components array. But from an API standpoint they may never want to fully commit to that order being linearly guaranteed.

I found this script a while ago and it put a smile on my face… hopefully it will for you to.
I think it was from here https://www.assetstore.unity3d.com/en/#!/content/18393 an asset called “Reorder My Components” which is free.
I have edited the script I am posting below, so download the asset above if you want the original. I applied the few bug fixes the people in the asset comments gave, as well as changing the GUI a bit (such as adding a scroll). I think the gui needs to be better, but I dont really know gui stuff, so maybe someone can help with that. I would have also liked if instead of going to “Window → ReorderComponents” to open the window, if there is a way to have a button right over the inspectors “Add Component” Button or something that would open this window, or better yet, not need to even open a window and just click and drag the components themselves.
I also think I ran into a few bugs and what not, but overall it was a huge time saver.
I have not used it a lot though, so I dont know if there are any scary bugs such as stuff getting deleted or something, so I guess use at your own risk, but I think there shouldnt be issues like that.

The script must be put inside a folder called Editor in your project.
To use it, have your gameobject selected and click on “Window → ReorderComponents”
There, you can click on those button looking things with your components name on them and drag them to where you want them.

Click for code

using UnityEngine;
using UnityEditor;

[InitializeOnLoad]
[ExecuteInEditMode]
public class ReorderComponents : EditorWindow
{

    int activeButton;
    int tempButtonIndex;
    int lastButtonIndex;
    bool mouseDown;
    int[] newIndexes;

    Texture2D buttonActiveBackground = Texture2D.blackTexture;

    public Vector2 scrollPosition = Vector2.zero;

    [MenuItem("Window/Reorder Components")]
    private static void ShowWindow()
    {
        ReorderComponents windowHndle = (ReorderComponents)EditorWindow.GetWindow(typeof(ReorderComponents));
        windowHndle.autoRepaintOnSceneChange = true;
    }

    void OnInspectorUpdate()
    {
        Repaint();
    }

    void OnGUI()
    {
        //This allows you to work on prefabs that are in the project view, as well as prevents error of clicking non gameobject
        Transform currentTransform;
        if(Selection.GetFiltered(typeof(Transform), SelectionMode.Unfiltered) != null && Selection.GetFiltered(typeof(Transform), SelectionMode.Unfiltered).Length > 0)
        {
            currentTransform = (Transform)Selection.GetFiltered(typeof(Transform), SelectionMode.Unfiltered)[0];
        }else{
            currentTransform = Selection.activeTransform;
        }

        if(currentTransform != null)
        {
            Component[] comps = currentTransform.GetComponents<Component>();

            Rect currentWindowRect = EditorWindow.GetWindow(typeof(ReorderComponents)).position;
            scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUIStyle.none, GUI.skin.verticalScrollbar, GUILayout.Height(currentWindowRect.height));

            #region graphic templates
            //buttonActiveBackground.SetPixel(0, 0, Color.gray);
            //buttonActiveBackground.Apply();

            GUIStyle buttonStyle = new GUIStyle(GUI.skin.button);
            buttonStyle.alignment = TextAnchor.MiddleLeft;
            buttonStyle.fixedHeight = 25;
            buttonStyle.margin = new RectOffset (4, 4, 4, 4);
    
            GUIStyle buttonDisabledStyle = new GUIStyle(GUI.skin.button);
            buttonDisabledStyle.alignment = TextAnchor.MiddleLeft;
            buttonDisabledStyle.fixedHeight = 25;
            buttonDisabledStyle.margin = new RectOffset (4, 4, 4, 4);
            buttonDisabledStyle.normal.textColor = Color.gray;
    
            GUIStyle buttonActiveStyle = new GUIStyle();
            buttonActiveStyle.alignment = TextAnchor.MiddleLeft;
            buttonActiveStyle.fixedHeight = 25;
            buttonActiveStyle.margin = new RectOffset (4, 4, 4, 4);
            buttonActiveStyle.normal.background = buttonActiveBackground;
            buttonActiveStyle.normal.textColor = Color.gray;
            #endregion

            // Check if mouse button gets pressed down and see which button is below mouse
            if(!mouseDown && Event.current.type == EventType.MouseDown)
            {
                activeButton = Mathf.FloorToInt(Event.current.mousePosition.y / 29);
        
                if(comps[activeButton].GetType().ToString() == "UnityEngine.Transform")
                {
                    mouseDown = false;
                }else{
                    mouseDown = true;
                    lastButtonIndex = activeButton;
            
                    newIndexes = new int[comps.Length];
                    for(int i=0; i<comps.Length; i++)
                    {
                        newIndexes[i] = i;
                    }
                }
            }
    
            // Mouse button released
            if(mouseDown && Event.current.type == EventType.MouseUp)
            {
                mouseDown = false;
        
                // Reorder components
                int positionsToMove = Mathf.RoundToInt(Mathf.Abs(tempButtonIndex - activeButton));
        
                if(positionsToMove > 0)
                {
                    int direction = (tempButtonIndex - activeButton) / Mathf.Abs(tempButtonIndex - activeButton);
        
                    for(int i=0; i<positionsToMove; i++)
                    {
                        if(direction > 0)
                        {
                            UnityEditorInternal.ComponentUtility.MoveComponentDown(comps[activeButton + i]);
                        }
                        if(direction < 0)
                        {
                            UnityEditorInternal.ComponentUtility.MoveComponentUp(comps[activeButton - i]);
                        }
                
                        comps = currentTransform.GetComponents<Component>();
                    }
                }
            }
    
            // Draw buttons
            for(int i=0; i<comps.Length; i++)
            {
                int j = i;
        
                if(mouseDown)
                {
                    j = newIndexes[i];
                }
    
                string componentName = comps[j].GetType().ToString();
    
                GUIStyle style = buttonStyle;
        
                if(mouseDown && i == tempButtonIndex) {style = buttonActiveStyle;}
                if(componentName == "UnityEngine.Transform") {style = buttonDisabledStyle;}
        
                GUILayout.Button(componentName, style);
            }
    
            // If mouse button is down, draw the extra button
            if(mouseDown)
            {
                Rect buttonPosition = new Rect(Event.current.mousePosition.x - Screen.width/2, Event.current.mousePosition.y - 12.5f, Screen.width - 10, 25);
                GUI.Button(buttonPosition, comps[activeButton].GetType().ToString(), buttonStyle);
            }
    
            // Get index for the new temp button
            if(mouseDown)
            {
                int tmp = Mathf.FloorToInt(Event.current.mousePosition.y / 29);
        
                if(tmp > comps.Length - 1)
                {
                    tmp = comps.Length - 1;
                }
        
                if(tmp < 0)
                {
                    tmp = 0;
                }
        
                if(comps[tmp].GetType().ToString() != "UnityEngine.Transform")
                {
                    tempButtonIndex = tmp;
                }
                        
                if(tempButtonIndex != lastButtonIndex)
                {
                    int temp = newIndexes[lastButtonIndex];
                    newIndexes[lastButtonIndex] = newIndexes[tempButtonIndex];
                    newIndexes[tempButtonIndex] = temp;
        
                    lastButtonIndex = tempButtonIndex;
                }
            }

            GUI.EndScrollView();
        }
    }
}
1 Like

I have container objects that call on other components they get with a list from GetComponents(). The GetComponents() function returns the array in the same order as they are displayed in the editor, and this in turn defines the order of operations, which IS VERY IMPORTANT.

So no, it isn’t just cosmetics and this feature would be very nice indeed!

This would be incredibly useful for orginizing camera effects order.
I also like to attach a Readme script to a gameobject and having it be the first component on the gameObject.

2534752–175983–_README.cs (232 Bytes)

1 Like

In Unity 5.4 I get the error

“get_blackTexture is not allowed to be called from a ScriptableObject constructor (or instance field initializer), call it in OnEnable instead. Called from ScriptableObject ‘ReorderComponents’.”

There was a blog post about it a couple of days ago.

http://blogs.unity3d.com/2016/06/06/serialization-monobehaviour-constructors-and-unity-5-4/

I dont have unity 5.4 to test this, but I assume you could change this

Texture2D buttonActiveBackground = Texture2D.blackTexture;

to this

Texture2D buttonActiveBackground;

void OnEnable()
{
    buttonActiveBackground = Texture2D.blackTexture;
}

Also, the new 5.3.5 patch states this…

  • Editor: Fixed changing order of components not getting saved. It now also support undo. (764986)

https://unity3d.com/unity/whats-new/unity-5.3.5

So keep that in mind =)

Yep, that does the trick.

1 Like

Like this? XT Reorder Asset Store Link