- Home /
Sortlayer Renderer Extension
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.
Anyone knows how to do the same extension in Shuriken?
// SortLayerRendererExtension.cs
// Author:
// Yves J. Albuquerque <yves.albuquerque@gmail.com>
// Last Update:
// 27-12-2013
//Put this file into a folder named Editor.
//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
using System;
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
using System.Reflection;
[CanEditMultipleObjects()]
[CustomEditor(typeof(Renderer),true)]
public class SortLayerRendererExtension : Editor
{
Renderer renderer;
Renderer[] childsRenderer;
string[] sortingLayerNames;
int selectedOption;
bool applyToChild = false;
bool applyToChildOldValue = false;
void OnEnable()
{
sortingLayerNames = GetSortingLayerNames();
renderer = (target as Renderer).gameObject.renderer;
if ((target as Renderer).transform.childCount > 1)
childsRenderer = (target as SortingLayerExposed).transform.GetComponentsInChildren<Renderer>();
for (int i = 0; i<sortingLayerNames.Length;i++)
{
if (sortingLayerNames[i] == renderer.sortingLayerName)
selectedOption = i;
}
}
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (!renderer)
{
return;
}
EditorGUILayout.LabelField("\n");
selectedOption = EditorGUILayout.Popup("Sorting Layer", selectedOption, sortingLayerNames);
if (sortingLayerNames[selectedOption] != renderer.sortingLayerName)
{
Undo.RecordObject(renderer, "Sorting Layer");
if (!applyToChild)
renderer.sortingLayerName = sortingLayerNames[selectedOption];
else
{
for (int i = 0; i<childsRenderer.Length;i++)
{
childsRenderer[i].sortingLayerName = sortingLayerNames[selectedOption];
}
}
EditorUtility.SetDirty(renderer);
}
int newSortingLayerOrder = EditorGUILayout.IntField("Order in Layer", renderer.sortingOrder);
if (newSortingLayerOrder != renderer.sortingOrder)
{
Undo.RecordObject(renderer, "Edit Sorting Order");
renderer.sortingOrder = newSortingLayerOrder;
EditorUtility.SetDirty(renderer);
}
applyToChild = EditorGUILayout.ToggleLeft("Apply to Childs", applyToChild);
if (applyToChild != applyToChildOldValue)
{
for (int i = 0; i<childsRenderer.Length;i++)
{
childsRenderer[i].sortingLayerName = sortingLayerNames[selectedOption];
}
Undo.RecordObject(renderer, "Apply Sort Mode To Child");
applyToChildOldValue = applyToChild;
EditorUtility.SetDirty(renderer);
}
}
// Get the sorting layer names
public string[] GetSortingLayerNames()
{
Type internalEditorUtilityType = typeof(InternalEditorUtility);
PropertyInfo sortingLayersProperty = internalEditorUtilityType.GetProperty("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic);
return (string[])sortingLayersProperty.GetValue(null, new object[0]);
}
// Get the unique sorting layer IDs -- tossed this in for good measure
public int[] GetSortingLayerUniqueIDs()
{
Type internalEditorUtilityType = typeof(InternalEditorUtility);
PropertyInfo sortingLayerUniqueIDsProperty = internalEditorUtilityType.GetProperty("sortingLayerUniqueIDs", BindingFlags.Static | BindingFlags.NonPublic);
return (int[])sortingLayerUniqueIDsProperty.GetValue(null, new object[0]);
}
}
Answer by YJack · Dec 28, 2013 at 11:27 PM
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
// RendererLayerEditor.cs
// Author:
// Yves J. Albuquerque <yves.albuquerque@gmail.com>
// Last Update:
// 28-12-2013
//Put this file into a folder named Editor.
//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
using System;
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
using System.Reflection;
[CanEditMultipleObjects()]
[CustomEditor(typeof(RendererLayer))]
public class RendererLayerEditor : Editor
{
ParticleSystem[] l_particleSystems; //reference to our particle systems
Renderer[] l_renderers;//reference to our renderers
string[] sortingLayerNames;//we load here our Layer names to be displayed at the popup GUI
int popupMenuIndex;//The selected GUI popup Index
bool applyToChild = false;//Turn on/off if the effect will be extended to all renderers in child transforms
bool applyToChildOldValue = false;//Used this old value to detect changes in applyToChild boolean
/// <summary>
/// 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
/// </summary>
void OnEnable()
{
sortingLayerNames = GetSortingLayerNames(); //First we load the name of our layers
l_particleSystems = (target as RendererLayer).gameObject.GetComponentsInChildren<ParticleSystem>();//Then we load our ParticleSystems
l_renderers = new Renderer[l_particleSystems.Length];//and Initialize our renderers array with the right size
for (int i = 0; i<l_particleSystems.Length;i++) //here we loads all renderers to our renderersarray
{
l_renderers[i] = l_particleSystems[i].renderer;
}
for (int i = 0; i<sortingLayerNames.Length;i++) //here we initialize our popupMenuIndex with the current Sort Layer Name
{
if (sortingLayerNames[i] == l_particleSystems[0].renderer.sortingLayerName)
popupMenuIndex = i;
}
}
/// <summary>
/// OnInspectorGUI is where the magic happens. Here we draw and change all the stuff
/// </summary>
public override void OnInspectorGUI()
{
DrawDefaultInspector(); //first we draw our DefaultInspector
if (l_renderers.Length == 0) //if there`s no Renderer at this object
{
return; //returns
}
popupMenuIndex = EditorGUILayout.Popup("Sorting Layer", popupMenuIndex, sortingLayerNames);//The popup menu is displayed simple as that
int newSortingLayerOrder = EditorGUILayout.IntField("Order in Layer", l_renderers[0].sortingOrder); //Specifies the order to be drawed in this particular SortLayer
applyToChild = EditorGUILayout.ToggleLeft("Apply to Childs", applyToChild);//If this change will be applyed to every renderer or just this one
if (sortingLayerNames[popupMenuIndex] != l_renderers[0].sortingLayerName ||
newSortingLayerOrder != l_renderers[0].sortingOrder ||
applyToChild != applyToChildOldValue) //if there`s some change
{
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
if (applyToChild) //change sortingLayerName and sortingOrder in each Renderer
{
for (int i = 0; i<l_renderers.Length;i++)
{
l_renderers[i].sortingLayerName = sortingLayerNames[popupMenuIndex];
l_renderers[i].sortingOrder = newSortingLayerOrder;
}
}
else //or at least at this one
{
l_renderers[0].sortingLayerName = sortingLayerNames[popupMenuIndex];
l_renderers[0].sortingOrder = newSortingLayerOrder;
}
EditorUtility.SetDirty(l_renderers[0]); //saves
}
}
// Get the sorting layer names
public string[] GetSortingLayerNames()
{
Type internalEditorUtilityType = typeof(InternalEditorUtility);
PropertyInfo sortingLayersProperty = internalEditorUtilityType.GetProperty("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic);
return (string[])sortingLayersProperty.GetValue(null, new object[0]);
}
}
But unfortunately you need to put a code in your Shuriken Effect. An almost empty code with a particular name. Sad but true.
using UnityEngine;
public class RendererLayer : MonoBehaviour{}