Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Sort Layer Renderer Extension

Discussion in 'Scripting' started by YJack, Dec 28, 2013.

  1. YJack

    YJack

    Joined:
    Apr 7, 2010
    Posts:
    44
    Hello Guys,
    As we know since Unity 4.3, Unity have a sort layer manager. This feature is exposed and fully manageable from Edit->Project Settings->Tags and Layers.
    Every Renderer have some exposed variables to deal with the sort layer but only the Sprite Renderer has it exposed on the inspector.
    So I find a way to do an extension to Unity Renderers, adding sort layer options as in Sprite Renderer to every Renderer. (so you can use it at TrailRenderer, LineRenderer, ParticleLegacyRenderer and etc...)
    I did it yesterday so I`m not sure, at this moment, if it really works as it should work in all cases. The code is also a little dirt (sorry for that).
    I also added a include child toggle option because well... it`s quite useful.

    I tried to do the same in Shuriken Particle System but I`m new in this Custom Editor thing and I`m not able to change Shuriken Particle System without destroy that charming look from Shuriken Particle System Inspector.

    Code (csharp):
    1.  
    2. //  SortLayerRendererExtension.cs
    3. //   Author:
    4. //       Yves J. Albuquerque <yves.albuquerque@gmail.com>
    5. //  Last Update:
    6. //       27-12-2013
    7. //Put this file into a folder named Editor.
    8. //Based on Nick`s code at https://gist.github.com/nickgravelyn/7460288 and Ivan Murashko solution at http://forum.unity3d.com/threads/210683-List-of-sorting-layers?p=1432958&viewfull=1#post1432958 aput by Guavaman at http://answers.unity3d.com/questions/585108/how-do-you-access-sorting-layers-via-scripting.html
    9. using System;
    10. using UnityEngine;
    11. using UnityEditor;
    12. using UnityEditorInternal;
    13. using System.Reflection;
    14.  
    15. [CanEditMultipleObjects()]
    16. [CustomEditor(typeof(Renderer),true)]
    17. public class SortLayerRendererExtension : Editor
    18. {
    19.     Renderer renderer;
    20.     Renderer[] childsRenderer;
    21.     string[] sortingLayerNames;
    22.  
    23.     int selectedOption;
    24.     bool applyToChild = false;
    25.     bool applyToChildOldValue = false;
    26.  
    27.     void OnEnable()
    28.     {
    29.         sortingLayerNames = GetSortingLayerNames();
    30.         renderer = (target as Renderer).gameObject.renderer;
    31.         if ((target as Renderer).transform.childCount > 1)
    32.             childsRenderer = (target as SortingLayerExposed).transform.GetComponentsInChildren<Renderer>();
    33.  
    34.         for (int i = 0; i<sortingLayerNames.Length;i++)
    35.         {
    36.             if (sortingLayerNames[i] == renderer.sortingLayerName)
    37.                 selectedOption = i;
    38.         }
    39.     }
    40.  
    41.     public override void OnInspectorGUI()
    42.     {
    43.         DrawDefaultInspector();
    44.         if (!renderer)
    45.         {
    46.             return;
    47.         }
    48.  
    49.         EditorGUILayout.LabelField("\n");
    50.  
    51.         selectedOption = EditorGUILayout.Popup("Sorting Layer", selectedOption, sortingLayerNames);
    52.         if (sortingLayerNames[selectedOption] != renderer.sortingLayerName)
    53.         {
    54.             Undo.RecordObject(renderer, "Sorting Layer");
    55.             if (!applyToChild)
    56.                 renderer.sortingLayerName = sortingLayerNames[selectedOption];
    57.             else
    58.             {
    59.                 for (int i = 0; i<childsRenderer.Length;i++)
    60.                 {
    61.                     childsRenderer[i].sortingLayerName = sortingLayerNames[selectedOption];
    62.                 }
    63.             }
    64.             EditorUtility.SetDirty(renderer);
    65.         }
    66.  
    67.         int newSortingLayerOrder = EditorGUILayout.IntField("Order in Layer", renderer.sortingOrder);
    68.         if (newSortingLayerOrder != renderer.sortingOrder)
    69.         {
    70.             Undo.RecordObject(renderer, "Edit Sorting Order");
    71.             renderer.sortingOrder = newSortingLayerOrder;
    72.             EditorUtility.SetDirty(renderer);
    73.         }
    74.  
    75.         applyToChild = EditorGUILayout.ToggleLeft("Apply to Childs", applyToChild);
    76.         if (applyToChild != applyToChildOldValue)
    77.         {
    78.             for (int i = 0; i<childsRenderer.Length;i++)
    79.             {
    80.                 childsRenderer[i].sortingLayerName = sortingLayerNames[selectedOption];
    81.             }
    82.             Undo.RecordObject(renderer, "Apply Sort Mode To Child");
    83.             applyToChildOldValue = applyToChild;
    84.             EditorUtility.SetDirty(renderer);
    85.         }
    86.     }
    87.  
    88.     // Get the sorting layer names
    89.     public string[] GetSortingLayerNames()
    90.     {
    91.         Type internalEditorUtilityType = typeof(InternalEditorUtility);
    92.         PropertyInfo sortingLayersProperty = internalEditorUtilityType.GetProperty("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic);
    93.         return (string[])sortingLayersProperty.GetValue(null, new object[0]);
    94.     }
    95.    
    96.     // Get the unique sorting layer IDs -- tossed this in for good measure
    97.     public int[] GetSortingLayerUniqueIDs()
    98.     {
    99.         Type internalEditorUtilityType = typeof(InternalEditorUtility);
    100.         PropertyInfo sortingLayerUniqueIDsProperty = internalEditorUtilityType.GetProperty("sortingLayerUniqueIDs", BindingFlags.Static | BindingFlags.NonPublic);
    101.         return (int[])sortingLayerUniqueIDsProperty.GetValue(null, new object[0]);
    102.     }
    103. }
    104.  
    EDIT:
    Still wanted some help here but I did a little trick. Not the wanted solution but worked until someone comes with an integrated solution for Shuriken.

    This is the Editor code
    Code (csharp):
    1.  
    2. //  RendererLayerEditor.cs
    3. //   Author:
    4. //       Yves J. Albuquerque <yves.albuquerque@gmail.com>
    5. //  Last Update:
    6. //       28-12-2013
    7. //Put this file into a folder named Editor.
    8. //Based on Nick`s code at https://gist.github.com/nickgravelyn/7460288 and Ivan Murashko solution at http://forum.unity3d.com/threads/210683-List-of-sorting-layers?p=1432958&viewfull=1#post1432958 aput by Guavaman at http://answers.unity3d.com/questions/585108/how-do-you-access-sorting-layers-via-scripting.html
    9. using System;
    10. using UnityEngine;
    11. using UnityEditor;
    12. using UnityEditorInternal;
    13. using System.Reflection;
    14.  
    15. [CanEditMultipleObjects()]
    16. [CustomEditor(typeof(RendererLayer))]
    17. public class RendererLayerEditor : Editor
    18. {
    19.     ParticleSystem[] l_particleSystems; //reference to our particle systems
    20.     Renderer[] l_renderers;//reference to our renderers
    21.  
    22.     string[] sortingLayerNames;//we load here our Layer names to be displayed at the popup GUI
    23.     int popupMenuIndex;//The selected GUI popup Index
    24.     bool applyToChild = false;//Turn on/off if the effect will be extended to all renderers in child transforms
    25.     bool applyToChildOldValue = false;//Used this old value to detect changes in applyToChild boolean
    26.  
    27.     /// <summary>
    28.     /// Raises the enable event. We use it to set some references and do some initialization. I don`t figured out how to make a variable persistent in Unity Editor yet so most of the codes here can useless
    29.     /// </summary>
    30.     void OnEnable()
    31.     {
    32.         sortingLayerNames = GetSortingLayerNames(); //First we load the name of our layers
    33.         l_particleSystems = (target as RendererLayer).gameObject.GetComponentsInChildren<ParticleSystem>();//Then we load our ParticleSystems
    34.         l_renderers = new Renderer[l_particleSystems.Length];//and Initialize our renderers array with the right size
    35.  
    36.         for (int i = 0; i<l_particleSystems.Length;i++) //here we loads all renderers to our renderersarray
    37.         {
    38.             l_renderers[i] = l_particleSystems[i].renderer;
    39.         }
    40.  
    41.         for (int i = 0; i<sortingLayerNames.Length;i++) //here we initialize our popupMenuIndex with the current Sort Layer Name
    42.         {
    43.             if (sortingLayerNames[i] == l_particleSystems[0].renderer.sortingLayerName)
    44.                 popupMenuIndex = i;
    45.         }
    46.     }
    47.  
    48.     /// <summary>
    49.     /// OnInspectorGUI is where the magic happens. Here we draw and change all the stuff
    50.     /// </summary>
    51.     public override void OnInspectorGUI()
    52.     {
    53.         DrawDefaultInspector(); //first we draw our DefaultInspector
    54.  
    55.         if (l_renderers.Length == 0) //if there`s no Renderer at this object
    56.         {
    57.             return; //returns
    58.         }
    59.  
    60.         popupMenuIndex = EditorGUILayout.Popup("Sorting Layer", popupMenuIndex, sortingLayerNames);//The popup menu is displayed simple as that
    61.         int newSortingLayerOrder = EditorGUILayout.IntField("Order in Layer", l_renderers[0].sortingOrder); //Specifies the order to be drawed in this particular SortLayer
    62.         applyToChild = EditorGUILayout.ToggleLeft("Apply to Childs", applyToChild);//If this change will be applyed to every renderer or just this one
    63.  
    64.         if (sortingLayerNames[popupMenuIndex] != l_renderers[0].sortingLayerName ||
    65.             newSortingLayerOrder != l_renderers[0].sortingOrder ||
    66.             applyToChild != applyToChildOldValue) //if there`s some change
    67.         {
    68.             Undo.RecordObject(l_renderers[0], "Change Particle System Renderer Order"); //first let record this change into Undo class so if the user did a mess, he can use ctrl+z to undo
    69.  
    70.             if (applyToChild) //change sortingLayerName and sortingOrder in each Renderer
    71.             {
    72.                 for (int i = 0; i<l_renderers.Length;i++)
    73.                 {
    74.                     l_renderers[i].sortingLayerName = sortingLayerNames[popupMenuIndex];
    75.                     l_renderers[i].sortingOrder = newSortingLayerOrder;
    76.                 }
    77.             }
    78.             else //or at least at this one
    79.             {
    80.                 l_renderers[0].sortingLayerName = sortingLayerNames[popupMenuIndex];
    81.                 l_renderers[0].sortingOrder = newSortingLayerOrder;
    82.             }
    83.  
    84.             EditorUtility.SetDirty(l_renderers[0]); //saves
    85.         }
    86.     }
    87.  
    88.     // Get the sorting layer names
    89.     public string[] GetSortingLayerNames()
    90.     {
    91.         Type internalEditorUtilityType = typeof(InternalEditorUtility);
    92.         PropertyInfo sortingLayersProperty = internalEditorUtilityType.GetProperty("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic);
    93.         return (string[])sortingLayersProperty.GetValue(null, new object[0]);
    94.     }
    95. }
    96.  
    But unfortunately you need to put a code in your Shuriken Effect. An almost empty code with a particular name. Sad but true.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. public class RendererLayer : MonoBehaviour{}
    4.  
     
    Last edited: Dec 28, 2013
    howong and sandolkakos like this.
  2. moatdd

    moatdd

    Joined:
    Jan 13, 2013
    Posts:
    178
    IT WORKS WITH PARTICLES! Thank you for making this extension! You saved me some trouble!
     
    YJack likes this.
  3. SanSolo

    SanSolo

    Joined:
    Feb 25, 2014
    Posts:
    85
    I'm not using Shuriken, but need help showing the sorting layer for non sprites. How exactly do I proceed with this?
     
  4. Marzoa

    Marzoa

    Joined:
    Dec 2, 2012
    Posts:
    50
    I want to try this but it isn't working for me. The first script doesn't even compile, it says:

    .../ShortLayerRendererExtension.cs(77,77): Error CS0246: The type or namespace name `SortingLayerExposed' could not be found. Are you missing a using directive or an assembly reference? (CS0246) (Assembly-CSharp-Editor)

    Where is that class defined?

    Bests!
     
  5. Marzoa

    Marzoa

    Joined:
    Dec 2, 2012
    Posts:
    50
  6. SanSolo

    SanSolo

    Joined:
    Feb 25, 2014
    Posts:
    85
    Still wondering how to get it working.
     
  7. SanSolo

    SanSolo

    Joined:
    Feb 25, 2014
    Posts:
    85
    Got it working.
     
  8. s_guy

    s_guy

    Joined:
    Feb 27, 2013
    Posts:
    102
  9. YJack

    YJack

    Joined:
    Apr 7, 2010
    Posts:
    44
    Hello guys,
    I've included an updated version of Sort Layer Renderer at Asset Store. (Compatible with Unity 5)
    It's included into a tutorial called ESR (Now, for FREE).
    Best regards,
     
    howong likes this.