Search Unity

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.