What is the most accurate moment when TextMeshPro text is shown on screen

I am working on a time-sensitive application using Unity. I would like to know what is the most precise moment in which a text is shown to a user on the screen. I am currently using TextMeshPro in a canvas to display my text. My code is a MonoBehaviour that looks like this:


    // Stimulus text 
    public TextMeshProUGUI stimulus;

    // Last stimulus delivered
    private string previousStimulus = "";

    // Start is called before the first frame update
    void Start()
    {
        stimulus.text = "";
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    // Stimulate
    public void DisplayStimulus(string stimulusText)
    {
        previousStimulus = stimulus.text;
        stimulus.text = stimulusText;
    }

    private void OnRenderObject()
    {
        
        if(!stimulus.text.Equals("") && !stimulus.text.Equals(previousStimulus))
        {
            // A new stimulus was rendered, perform time-sensitive action when stimulus is displayed
            previousStimulus=stimulus.text;
        }
    }

I read about the default rendering pipeline and thought that the time-sensitive action should happen in the OnRenderObject callback. Eventhough the Monobehavior is attached to a UI object, is this callback appropriate? My ultimate goal is to perform an action as soon as I know that the text is shown on the screen.

thank you.

Tricky one, this…

While I don’t have a definitive answer, you need to know that TMP is changing. See this post on Unity’s UI Systems forum. Even if TMP is not currently rendered as part of the OnGUI loop, I think it will be in future. The problem with that is that OnGUI can be rendered multiple times in a single frame. if that’s the case, I don’t think you can know exactly when TMP is rendered.

In my previous university role, I did research into “Just Noticeable Difference” (JND) primarily in the area of audio but I touched on visual perception as well. To be honest, if you are able to run your app at above 10 frames per second, there will be little to no difference in timing. The fastest human reaction is barely better than 150ms, roughly 7 frames per second. That means that you can trust the render timings, proving you don’t have any glitches (garbage collection being the biggest threat).

You may in the end not want to use OnGUI, since it can run multiple times per frame. An experiment I might try myself is to see just how often it’s called in different circumstances by logging OnGUI callbacks within each frame and having a Coroutine register frame timings. Could be interesting…