Most efficient way to get TextMeshPros in scene?

Howdy folks,

I’m working on a game that uses heaps of asset bundles and addressables. Some of them are built with other versions of Unity/TextMeshPro, which as you may know causes a bug where the material of the text appears ‘broken’ in the editor (Pink squares) but looks fine in build.

In my game we resolve this by running an editor script that refreshes the material on all TextMeshPros every second.

This is basically what the refresh logic looks like:

private static void RefreshTextMaterialsInProject()
    {
      TextMeshProUGUI[] texts = Resources.FindObjectsOfTypeAll<TextMeshProUGUI>();

      foreach (TextMeshProUGUI text in texts)
      {
        ReplaceShaderForEditor(text.material);
        ReplaceShaderForEditor(text.materialForRendering);
      }
    }

   
    private static void ReplaceShaderForEditor(Material material)
    {
      if (material == null) return;

      var shaderName = material.shader.name;
      var shader = Shader.Find(shaderName);

      if (shader != null) material.shader = shader;
    }

This script works, but is inefficient. This is mainly caused by calling Resources.FindObjectsOfTypeAll<TextMeshProUGUI>() every second.
I think it would be a huge improvement if I were to run this by calling GetComponentsInChildren<TextMeshProUGUI>() on all alive root GameObjects, but I’m not sure how to get them.

Does anyone have any advice on this? Would appreciate any help I could get. Thank you.

I don’t follow why you need to run this periodically but you gain access to the Transform hierarchy with the Scene type. There you can use the GetRootGameObjects method using the overload that allows you to pass (and more importantly reuse) the List. You can then iterate all the active ones again using the overloads that allow you to pass and reuse a list. Don’t use the ones that create an array for you with the results.

1 Like

I mean, ideally you’d rebuild the asset bundles to use the newest version. A pain for sure but you do it once and then it just works. Also, why is it necessary to update every second? You can’t simply run the script once and update the material for each asset when it is loaded?

1 Like