• Runtimes
  • [Unity] Plugin to sort Spine with SpriteRenderer's layer

Normally Unity put Spine character in the "Default" sorting layer (Because it is a MeshRenderer) which will be hard to manage when used with other SpriteRenderer. You will be forced to move the Default layer around to sort them since the sorting layer is prioritised over Z transform value.

With this script you will have the two box normally seen on SpriteRenderer exposed on your MeshRenderer. (These 2 value exist in the regular Renderer all along but not exposed in the inspector.) The content of Sorting Layer drop down will be just like what you see on your SpriteRenderer minus the last row "Add Sorting Layer..."

I put together other's code on exposing these 2 values on the inspector and added more functionality like mimicking drop down menu of SpriteRenderer's and used SerializedProperty to enable undo/revert to prefab which took me quite a few hours so I thought about sharing with anyone that might having the same problem as me. Now you can freely arrange your Spine character anywhere with your other Sprite objects. In the same layer, MeshRenderer still can draw on top of each other using Z value as usual. (Not the case with SpriteRenderer where Z is ignored)

The acknowledgement of various scripts used to make this is on the comment section of the code. Just put this code in your Editor folder and it should work.

using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditorInternal;
using System.Reflection;
using System;
#endif

//Expose SortingLayer & SortingOrder on MeshRenderer
//With nice drop down and revert to prefab functionality.

//Base exposing code by neror http://forum.unity3d.com/threads/212006-Drawing-order-of-Meshes-and-Sprites
//Get all sorting layer name and ID by guavaman & Ivan.Murashko http://answers.unity3d.com/questions/585108/how-do-you-access-sorting-layers-via-scripting.html
//Sorting Layer drop down menu, bold text on prefab override, revert to prefab and instant update on Order change functionality by 5argon

[CustomEditor(typeof(MeshRenderer))]

public class MeshRendererSortingLayersEditor : Editor
{

public override void OnInspectorGUI()
{

    base.OnInspectorGUI();

    serializedObject.Update();

    SerializedProperty sortingLayerID = serializedObject.FindProperty("m_SortingLayerID");
    SerializedProperty sortingOrder = serializedObject.FindProperty("m_SortingOrder");

    MeshRenderer renderer = target as MeshRenderer;

    Rect firstHoriz = EditorGUILayout.BeginHorizontal();

    EditorGUI.BeginChangeCheck();

    EditorGUI.BeginProperty(firstHoriz,GUIContent.none,sortingLayerID);

    string[] layerNames = GetSortingLayerNames();
    int[] layerID = GetSortingLayerUniqueIDs();

    int selected = -1;
    //What is selected?
    int sID = sortingLayerID.intValue;
    for(int i = 0 ; i < layerID.Length ; i++)
    {
        //Debug.Log(sID + " " + layerID[i]);
        if(sID == layerID[i])
        {
            selected = i;
        }
    }

    if(selected == -1)
    {
        //Select Default.
        for(int i = 0 ; i < layerID.Length ; i++)
        {
            if(layerID[i] == 0)
            {
                selected = i;
            }
        }
    }

    selected = EditorGUILayout.Popup("Sorting Layer" ,selected,layerNames);

    //Translate to ID
    sortingLayerID.intValue = layerID[selected];


    EditorGUI.EndProperty();

    EditorGUILayout.EndHorizontal();

    EditorGUILayout.BeginHorizontal();
    EditorGUI.BeginChangeCheck();

    EditorGUILayout.PropertyField(sortingOrder,new GUIContent("Order in Layer"));


    EditorGUILayout.EndHorizontal();
    serializedObject.ApplyModifiedProperties();
}

public string[] GetSortingLayerNames() {
    Type internalEditorUtilityType = typeof(InternalEditorUtility);
    PropertyInfo sortingLayersProperty = internalEditorUtilityType.GetProperty("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic);
    return (string[])sortingLayersProperty.GetValue(null, new object[0]);
}

public int[] GetSortingLayerUniqueIDs() {
    Type internalEditorUtilityType = typeof(InternalEditorUtility);
    PropertyInfo sortingLayerUniqueIDsProperty = internalEditorUtilityType.GetProperty("sortingLayerUniqueIDs", BindingFlags.Static | BindingFlags.NonPublic);
    return (int[])sortingLayerUniqueIDsProperty.GetValue(null, new object[0]);
}

}
Related Discussions
...
  • Editado

Thanks for this!
Other people have made other solutions that require a different component to access MeshRenderer's "hidden" serialized properties. This seems cleaner to use because it's only one file and doesn't need extra components.

I think one reason why they opted not to do this was because maybe you were already using another custom MeshRendererInspector. But I doubt that's a lot of people.

Pretty cool! thanks for sharing 🙂

This is nice, would you mind if I include it in the official runtime?

I don't mind at all. Please do!

Edit : If this is becoming a part of official runtime I think those two should be in the SkeletonAnimation component section instead?

Also in Unity 4.5 you can have a nicer inspector by using the new attribute [Header] and [Space]
http://docs.unity3d.com/ScriptReference ... ibute.html
http://docs.unity3d.com/ScriptReference ... ibute.html
If you use [Header("_____")] the string will appear as a indented bold text! I don't know what would happen when run on older Unity version though?

un año más tarde

I think the better alternative is for these SortingLayer stuff to be a part of SkeletonRenderer's inspector.
A custom inspector script for MeshRenderer as part of Spine runtime seems like Spine exclusively claiming MeshRenderer.
People might have their own custom MeshRenderer inspector script. Though the custom script doesn't do anything Spine-specific and helps all cases, combining its functionality with another existing thing might not be something everyone can do.

That's my opinion.

The Header and Space DecoratorDrawers are for scripts that don't have custom inspector scripts. SkeletonAnimation and SkeletonComponent already have them.
I agree, these really are nice though. I plan to use them in all my MonoBehaviours.


This thread was brought up recently so I thought I'd post an update:
I added Sorting Layer fields a few months ago to SkeletonRenderer/SkeletonAnimation's inspector code so you have settable Sorting Layer and Order in Layer fields right there (similar to SpriteRenderer).

Note that these inspector fields access and modify the sibling MeshRenderer's hidden SortingLayer properties so it will be serialized as part of the Renderer and not the SkeletonRenderer/SkeletonAnimation component.

Also note that the above code posted by OP will no longer work for Unity 5. If you copy the code pattern in SkeletonRenderer's inspector code though, you can probably get it to work again.

4 días más tarde

even if i use the sorting layer parameter it doesn't work ... :/ only if i play around the z axes the sorting change are there any alternative solution ??

What doesn't work?