Hello, everyone.
I’m asking the question on behalf of my brutal and unshaven programmer partner from Russia.
In the new and shiny 4.3 version, Sprites can be given a rendering order in their layer. They also have something called Sorting Layers, which seems to relate to that as well.
However, when the scene combines both Sprites and Meshes, meshes do not have anything relating to rendering order, at least nothing I can find.
So, the question is, how can I place a mesh in rendering order relative to a sprite and vice versa?
I’ve been desperately searching for this as well. I can’t get any mesh which uses a MeshRenderer to draw over SpriteRenderers with an orthographic camera. I’ve tried everything I can think of short of drawing the MeshRenderers with different cameras. I’ve played with the z-order, I’ve even messed with the renderQueues on the materials. Nothing will draw over a SpriteRenderer.
If anyone’s interested, I threw together a quick editor script to expose the sorting layers on the MeshRenderer component in the inspector. Unfortunately, I couldn’t figure out how to find all of the layer names via script. So it’s just a text field. Use with care.
using UnityEngine;
using UnityEditor;
using System.Collections;
[CustomEditor(typeof(MeshRenderer))]
public class MeshRendererSortingLayersEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
MeshRenderer renderer = target as MeshRenderer;
EditorGUILayout.BeginHorizontal();
EditorGUI.BeginChangeCheck();
string name = EditorGUILayout.TextField("Sorting Layer Name", renderer.sortingLayerName);
if(EditorGUI.EndChangeCheck()) {
renderer.sortingLayerName = name;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUI.BeginChangeCheck();
int order = EditorGUILayout.IntField("Sorting Order", renderer.sortingOrder);
if(EditorGUI.EndChangeCheck()) {
renderer.sortingOrder = order;
}
EditorGUILayout.EndHorizontal();
}
}
(please forgive me in advance for my bad english)
Thx, man. this works! But if get “unlit/texture” shader, object will draw without this options (they use Z order). I think that not all shader programm working equally with sorting layers. But “sprites/default” shader works fine.
I was looking into this today and wanted to add some details to the thread for people in the future.
When using rendering order you’re setting the order in which Unity tells the GPU to draw the objects, nothing more. At that point it’s up to the shaders/materials to define how the GPU draws the object on the screen.
The sprite shaders all set “ZWrite Off” which tells the GPU not to write to the Z/depth buffer when drawing. This ensures a scene with nothing but sprites will have an empty Z/depth buffer and therefore every draw will put a sprite on screen.
If you want to integrate 3D objects in the scene, they don’t have to use the sprite shaders, but they also should set “ZWrite Off” so they also don’t write to the depth buffer. This can have some interesting consequences with 3D meshes (particularly if a single mesh goes behind itself, like with a 3D character). But for cubes or other simple convex meshes, it works quite well.
So the moral is: you don’t have to use the sprite shaders, but you can’t use the default mesh shaders because they all use the Z/depth buffer. Make a new shader (or copy one of the defaults) and set “ZWrite Off” and you’ll be good to go with sorting layers.
Nice solution neror. I combined your solution with a script to get a list of sorting layer names, to display a nice drop down list similar to ones in SpriteRenderer so you don’t have to type exact name. You can also have bold text on prefab override,undo and revert to prefab because I used the SerializedProperty.
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]);
}
}
Thanks, this solved a problem for me. Like mf_andreich said, I got it to work by setting the shader material to sprite-default. This works for particle systems too! Parent your particle system to an empty game object with a Mesh Renderer attached. Set the material on that empty game object to sprites-default and the particle system will display in the right sorting order too A bit of a work around…but we all love our particles
RDeluxe, can I ask you what kind of sorting problem you have with your scene?
The sorting system should be pretty flexible, when you know all the tricks
In Unity 5, sorting layer and order are exposed in the inspector for both the mesh renderer component and the particle system renderer. But the renderer still draws 3d meshes based on their z-position, maybe this will be fixed by the final release but I’m so thankful for this anyways.
Wrestling with a similar problem I found a different solution. I wanted a shader which plays nice with my sprite rendering layers but also allows me to mess with the texture’s offset and tiling numbers. Neror’s script worked great with the first part but unfortunately the Sprites/Default shader wouldn’t allow me to change the numbers.
Slightly different from what Nick Gravelyn said (although his post definitely sent me on the right track) I couldn’t get this to work by including the “ZWrite Off” flag to a customized version of the Unlit-Normal shader. Rather I had to add the below tag:
I had all this working fine in Unity 4.6 and below (using the advice in this thread - basically, meshes using custom shaders with ZWrite Off), but after upgrading to Unity 5 both the sorting layer and order of my meshes now seems to be being ignored (well, actually it’s maintained most of the time, but if there is any pattern as to when the order is or isn’t maintained, I have yet to discover it). Does anyone else have this problem, or know how to solve it?
The sorting layers aren’t so much a problem - the different layers are almost all using different shaders (and where they aren’t I could make two identical shaders so each layer has its own copy), so I could set the rendering Queue tag differently in the different shaders to force the order to be correct. And I guess there’s only one layer in which there’s a bunch of meshes requiring a certain order, and I could soon rewrite it to be drawn using Z-buffering. So there’s no emergency, it’s just my solution is a bit inelegant - it makes it more difficult if I want to change the drawing order at some point. So it would still be nice if anyone knows how to get the real sorting order working again in Unity 5.
Actually, none of my previously proposed workarounds work. Using Z-buffering for transparent sprites doesn’t work because if the background has two layers, front and back, and only the back layer of the background has been drawn before the transparent sprite is drawn, then the transparent parts of the sprite end up showing the back layer of the background instead of the front layer.
I have found the problem though, that the sorting layers were being set in code by their id, where the id was assumed to be a small integer (similar to the id used for a collision layer). I see now that the sorting layer id is a big hashcode, but the strange thing is that the small integers, which I based on the order in which I’d created new sorting layers, did work fine in Unity 4 (hence my only having a problem when I upgraded), even though it’s undocumented. Anyway, I’ve switched to using the big hashcodes now, and everything is fine. To find out what the sorting layer IDs are, by the way, look at the table of sorting layers (under ‘Tags and Layers’ in Project Settings) while the editor is in Debug mode (one of the settings accessible from the drop-down menu at the top-right). Strangely, it displays the IDs as unsigned integers, but the SortingLayerID property will only take a signed integer, so some of the IDs you see in the editor may need 2^32 subtracting from them before you can use them.