Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 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
5
Question by Rudy Pangestu · Dec 27, 2013 at 12:01 PM · component

Change Component Order via Script

Hi all,

Is there any way to change component order via script?

We can do this by right-clicking the component in the inspector, then select move up/down. But I need to do this by code. Is it possible that way?

To make it more specific, I have 2 components that use OnRenderImage(). They need to be called in a specific order, or else the resulting image is wrong. I have tried to set the script execution order but it has no effect.

Any help is appreciated. Thanks!

Comment
Add comment · Show 2
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 Owen-Reynolds · Dec 27, 2013 at 01:45 PM 0
Share

If you can't do this, should be able to combine the code into one script. For example, rename them doAfterRender and have a new OnRenderImage in some script call both.

avatar image yoyo · Jan 14, 2015 at 09:19 PM 1
Share

See also (undocumented) UnityEditorInternal.ComponentUtility.$$anonymous$$oveComponentUp/Down. (Editor code only, not runtime.)

4 Replies

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

Answer by vexe · Dec 27, 2013 at 12:30 PM

One way to do this is by attaching a component, that references all the other components attached to the same gameObject, and then via some magical custom editor stuff, you could get something like this (an example of what I'm working on):

alt text

You could see those "U" and "D" buttons, which stand for Up/Down. You could use this object to sort the other components, and then when you want to render - you take the order of your components, from that component.

If this solutions works for you, let me know and I'll post the code I used to get this custom editor.


So, here's what I worked out for you:

alt text

Here's the sorter component, for which I will make a custom editor for - it just has a list of components:

 using UnityEngine;
 using System.Collections.Generic;

 public class ComponentSorter : MonoBehaviour
 {
     [HideInInspector]
     public List<Component> components;

     void OnGUI()
     {
         for (int i = 0; i < components.Count; i++) {
             GUI.Label(new Rect(Screen.width / 2, i * 25, 500, 50), components[i].ToString());
         }
     }
 }

And, here's where the magic happens:

ComponentSorterEditor.cs (put this in your Editor folder, if you don't have one, create it - "Assets/Editor")

 using UnityEngine;
 using UnityEditor;
 using System.Collections.Generic;
 
 [CustomEditor(typeof(ComponentSorter))]
 public class ComponentSorterEditor : Editor
 {
 private SerializedProperty components;
 private void OnEnable()
 {
     components = serializedObject.FindProperty("components");
 }
 public override void OnInspectorGUI()
 {
     DrawDefaultInspector();

     serializedObject.Update();
     PopulateComponents();
     GUILayout.Label(components.name, EditorStyles.boldLabel);

     for (int i = 0; i < components.arraySize; i++) {
         EditorGUILayout.BeginHorizontal();
         {
             EditorGUILayout.PropertyField(components.GetAt(i));

             if (GUILayout.Button("D", GUILayout.Width(20f))) {
                 components.MoveDown(i);
             }
             if (GUILayout.Button("U", GUILayout.Width(20f))) {
                 components.MoveUp(i);
             }
         }
         EditorGUILayout.EndHorizontal();
     }
     serializedObject.ApplyModifiedProperties();
 }
 private void PopulateComponents()
 {
     components.RemoveNullObjects();
     var targetGo = (serializedObject.targetObject as ComponentSorter).gameObject;
     var comps = targetGo.GetComponents<Component>();
     foreach (var comp in comps) {
         if (!components.Contains(comp)) {
             components.Add(comp);
         }
     }
 }

I think the code is pretty straight forward. One thing to note here, RemoveNullObjects is useful so that, if you remove a component, the components list will get populated accordingly in a way that you won't see nulls as the objects values.

See this video, to see what I'm talking about. (I solved it on the fly in a redundant way in the video, there was no need to clear out the whole array)

Here's the SerializedProperty extension methods. Don't be scared, they're just there to make your life easier. Feel free to modify.

One thing you'd probably wanna do is remove the ComponentSorter reference from the components themselves. That could be easily achieved by adding one more condition to the if that's adding the comps:

 if (!components.Contains(comp) && !(comp is ComponentSorter)) {
     components.Add(comp);
 }

When you want to render your stuff, you just do:

 var orderedComps = myStuffGo.GetComponent<ComponentSorter>().components;

Hope you like it :)


Answering your comment:

You'll get serializedObject for free when you inherit from Editor which is where its declared. As its name suggests, it's of type SerializedObject

If you don't want to use the custom editor, then you won't get a visual representation of what's going on.

If you insist, you could use the extension methods I have MoveUp and MoveDown methods 'inside' ComponentSorter:

They just need some modifications:

 public static List<T> Swap<T>(this List<T> list, int i, int j)
 {
     T temp = list[i];
     list[i] = list[j];
     list[j] = temp;
     return list;
 }

  • Codes are not tested from this point on **

    public class ComponentSorter : MonoBehaviour { public List components; public void MoveUp(int fromIndex) { int previous = fromIndex - 1; if (previous < 0) previous = prop.arraySize - 1; components.Swap(fromIndex, previous); } public void MoveDown(int fromIndex) { int next = (fromIndex + 1) % prop.arraySize; components.Swap(fromIndex, next); } }

(You could actually make the MoveUp and MoveDown list extensions as well, I'd go for that...)

If you don't like moving them by index, you could do:

 public void Move(Component c, bool up)
 {
    int index = components.IndexOf(c);
    if (index == -1) return; // component not found;
    if (up) MoveUp(index);
    else MoveDown(index);
 }

So... wanna move the Transform component? you could do:

 Move(components.Find(c => c is Transform) as Transform, true); // don't forget System.Linq;

One more thing you could do, write a generic move method:

 public void Move<T>(bool up) where T : Component
 {
    int index = components.FindIndex(c => c.GetType() == typeof(T)); // if you want to get any children of 'T' do "c => c.GetType().IsSubclassOf(typeof(T))
    if (index == -1) return; // component not found;
    if (up) MoveUp(index);
    else MoveDown(index);
 }

Use it like:

 // for pure convenience
 private const bool UP = true;
 private const bool DOWN = false;
 
 Move<Transform>(UP);

I suggest you keep the custom editor - it's very useful. If you do remove it, then you have to move the population of the components array, to the sorter as well...


inspector.png (14.7 kB)
sorter.png (19.9 kB)
Comment
Add comment · Show 10 · 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 Rudy Pangestu · Dec 27, 2013 at 12:35 PM 0
Share

Sorry, but what I need is runtime code, not editor code.

avatar image vexe · Dec 27, 2013 at 12:35 PM 1
Share

You could change their order at runtime as well, via code. And then call GetOrderdComponents to get the components, in the order that they're sorted in.

avatar image Rudy Pangestu · Dec 27, 2013 at 12:49 PM 0
Share

Well, it's worth a shot I suppose. Do you $$anonymous$$d if I asked for the code? :D

avatar image vexe · Dec 27, 2013 at 12:59 PM 1
Share

I'm testing it out for you atm, almost there...

avatar image Statement · Dec 27, 2013 at 01:17 PM 5
Share

It's possible to move the component order with a couple of undocumented methods but this applies to editor only:

 UnityEditorInternal.ComponentUtility.$$anonymous$$oveComponentUp (someComponent);
 UnityEditorInternal.ComponentUtility.$$anonymous$$oveComponentDown (someComponent);

Thought I'd mention it since the question touches on it, but unfortunately this won't work at runtime, which is the requirement for the OP. It may be helpful to other people. Use carefully, the name strongly indicates it's not meant to be publicly used. It may mean that the API may move or disappear some time in the future. It may also mean that you won't get little support, should the API contain bugs. I've used it for my own purposes and I can tell you at least it solved my problems (used Unity 4.3.1 at the time).

Show more comments
avatar image
6

Answer by idbrii · May 17, 2018 at 05:40 PM

Use the undocumented UnityEditorInternal.ComponentUtility.MoveComponentUp/Down to move components around at edit time. (Thanks to Statement for the tip.)

 static void MoveUp()
 {
     var sel = Selection.activeGameObject;
     var target_component = sel.GetComponent<MoveThisKindOfComponent>();
     UnityEditorInternal.ComponentUtility.MoveComponentUp(target_component);
 }

You could make an Editor with a button to fix the component order on the selected object (or search for objects that need to be fixed).

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
avatar image
0

Answer by Checkman44 · Jan 18, 2021 at 02:24 PM

I wrote a ComponentSorter component that sorts components by name. I used bubble sort because we can only move components up and down. After each component switch, I call GetComponents again so we have the same list order as in editor UI.

     public class ComponentSorter : MonoBehaviour
     {
         public void Sort()
         {
             var components = GetComponents<Component>().ToList();
             components.RemoveAll(x => x.GetType().ToString() == "UnityEngine.Transform");
 
             for (int p = 0; p <= components.Count - 2; p++)
             {
                 for (int i = 0; i <= components.Count - 2; i++)
                 {
                     Component c1 = components[i];
                     Component c2 = components[i + 1];
 
                     string name1 = c1.GetType().ToString().Split('.').Last();
                     string name2 = c2.GetType().ToString().Split('.').Last();
 
                     if (string.Compare(name1, name2) == 1)
                     {
                         ComponentUtility.MoveComponentUp(c2);
                         components = GetComponents<Component>().ToList();
                         components.RemoveAll(x => x.GetType().ToString() == "UnityEngine.Transform");
                     }
                 }
             }
 
             for (int i = 0; i < components.Count; i++)
             {
                 ComponentUtility.MoveComponentUp(this);
             }
         }
     }

And the custom editor class with the button:

     [CustomEditor(typeof(ComponentSorter))]
     public class ComponentSorterEditor: Editor
     {
         public override void OnInspectorGUI()
         {
             DrawDefaultInspector();
 
             ComponentSorter myScript = (ComponentSorter)target;
             if (GUILayout.Button("Sort Components"))
             {
                 myScript.Sort();
             }
         }
     }
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
avatar image
0

Answer by miracalious · Apr 22, 2021 at 11:36 PM

For anyone still reading this looking to simply move a component up or down in editor code (for doing something like ensuring background images show up behind text, etc):

 UnityEditorInternal.ComponentUtility.MoveComponentUp(yourComponentReference); 
 UnityEditorInternal.ComponentUtility.MoveComponentDown(yourComponentReference);
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

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

25 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

Related Questions

2D Animation does not start 1 Answer

What is the syntax for adding some generic type of component without an object reference? 1 Answer

Enforce component attachment 1 Answer

Enabling/disabling a component. 2 Answers

differences: generic GetComponent. 3 Answers


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