Sorting order in TextMeshPro

When I started learning Unity what baffled me is the inconsistency of implementations across modules. The worst offender in this regard is TextMeshPro, where in the script you can change the sorting order of the object but not in the Editor. The option to do this is simply missing, even though similar 2D Components have it exposed by default.

Component properties for Sprite Renderer

This is very useful when you’re working with a specific design that you want to implement, since matching the design visually is very important.

To work around this problem you have to create a new custom editor, which will help you place it into correct position without the need of adding Canvas component. To start create an empty script, name it whatever you want, this script will trigger the custom editor. In my case it’s Script_TMPSortingLayer. Edit the script and inside define a public integer with value of 0, this will be used to hold the value of the custom editor.

Script_TMPSortingLayer.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class Script_TMPSortingLayer : MonoBehaviour{
    public int sortingLayer = 0;
}

Create another C# script, this will be our Editor script. Inside many things are going to happen but the most important one is reassigning the value of sortingLayer to the TextMeshPro Component.

Editor_TMPSortingLayer.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using TMPro;


[CustomEditor(typeof(Script_TMPSortingLayer))]
public class Editor_TMPSortingLayer : Editor
{
    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        Script_TMPSortingLayer script = (Script_TMPSortingLayer)target;

        script.sortingLayer = EditorGUILayout.IntField("Sorting layer", script.sortingLayer);
        TextMeshProUGUI t = script.gameObject.GetComponent<TextMeshProUGUI>();
        if (t != null){
            t.canvas.sortingOrder = script.sortingLayer;
        }
    }
}

First we assign special attribute to the class that’s going to execute this Editor class for every class that’s the type of Script_TMPSortingLayer.

Next we’re creating a class that is inheriting from Editor class. To display the editor we need to override OnInspectorGUI() method. This method will be responsible for actually drawing the Editor when appropriate. Inside that, the first thing we’re doing is to update the serializedObject. Getting the reference to our script is pretty important, since we’re going to be getting the Compontent responsible for actually drawing text from GameObject.

EditorGUILayout.IntField is the method that creates the integer field in the Editor. It actually returns the integer, so we don’t have to worry about casting it back to integer. We’re assigning that value to not “loose it” as the Editor class might be reinitialized all over, thus we would loose our value.

It might come as a surprise to you but we’re not actually getting TextMeshPro Compontent but TextMeshProUGUI, which is a bit different but from my testing I’ve noticed that the TextMeshPro Component is not created in Editor, but TextMeshProUGUI is when creating TextMeshPro UI component.

It’s important to check whether or not our object is not null, since we can attach our script before we have added the TextMeshPro compontent. After that we can finally assign the correct sortingOrder to underlying TextMeshProUGUI’s canvas object.

The effect of our custom Editor script

Improvement

There are still ways of improving this script – for example changing the actual layer that’s assigned to the canvas object and exposing that for selection.

Now with that knowledge, go forth.

Leave a Reply

Your email address will not be published. Required fields are marked *