Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Feature Request Using unity built-in SortingLayer

Discussion in 'Scripting' started by Tony_Max, May 14, 2023.

  1. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    334
    In
    SpriteRenderer
    there is a field
    Sorting Layer
    which can be used to select one of the created by developer sorting layers (by default there is always 1 precreated "Default" layer). Unity already have all this stuff and I want to use it. I have custom render system so I want to be able to do next things
    * serialize layer as it happens in
    SpriteRenderer
    in my monobehaviours
    * get selected layer position in whole layer range (like if it is 1st layer in layer list, then I want to get 0 index)

    Is there a simple way of doing so without use reflection with unity classes and writing tones of editor code just to repeat what is already done but for some reason not public to use?

    UPD: Unity, please make such things public, you already have it in your components, just let us use it without tones of boilerplate code just to access to all your private members.
     
    Last edited: May 15, 2023
  2. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
  3. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    334
    This example creates custom editor for entire class. Also this editor only works if you dealing with
    SpriteRenderer
    and it just let you assign layer name
    string
    and sorting order as an index.

    What I need is: having serialized sorting layer as it appears with
    SpriteRenderer
    as a dropdown list of layers field.
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,769
    Well there is the
    UnityEngine.SortingLayer
    struct that I imagine is used internally. Weirdly, it's not serialisable, nor does it have a property drawer on it's own.

    Potentially all that's needed is a wrapper struct/class and a simple property drawer to bring this to parity on it's own.
     
    Tony_Max likes this.
  5. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    334
    I've found pretty simple solution here.

    You can copy code from here
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class SortingLayerAttribute : PropertyAttribute { }
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System.Reflection;
    4.  
    5. [CustomPropertyDrawer(typeof(SortingLayerAttribute))]
    6.     public class SortingLayerPropertyDrawer : PropertyDrawer
    7.     {
    8.         private const string SortingLayerFieldMethodName = "SortingLayerField";
    9.        
    10.         public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    11.         {
    12.             if (property.propertyType != SerializedPropertyType.Integer && property.propertyType != SerializedPropertyType.String)
    13.                 Debug.LogError("SortedLayer property should be an integer or string ( the layer id )");
    14.             else
    15.                 SortingLayerField(new GUIContent("Sorting Layer"), property, EditorStyles.popup, EditorStyles.label);
    16.         }
    17.  
    18.         public static void SortingLayerField(GUIContent label, SerializedProperty layerID, GUIStyle style, GUIStyle labelStyle)
    19.         {
    20.             var methodInfo = typeof(EditorGUILayout).GetMethod(SortingLayerFieldMethodName, BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(GUIContent), typeof(SerializedProperty), typeof(GUIStyle), typeof(GUIStyle) }, null);
    21.  
    22.             if (methodInfo == null)
    23.             {
    24.                 Debug.LogWarning($"{nameof(SortingLayerPropertyDrawer)} can't find {SortingLayerFieldMethodName}.");
    25.                 return;
    26.             }
    27.                
    28.             var parameters = new object[] { label, layerID, style, labelStyle };
    29.             methodInfo.Invoke(null, parameters);
    30.         }      
    31.     }
    Usage example
    Code (CSharp):
    1. public class Foo : MonoBehaviour
    2. {
    3.     [SortingLayer][SerializedFiled] _sortingLayerID;
    4.  
    5.     public int LayerIndex => UnityEngine.SortingLayer.GetLayerValueFromID(_sortingLayerID)
    6. }