Notes on TextMesh Pro
SubMesh Objects
True Shadow supports TMP. However, due to its use of submesh objects, additional code may be necessary.
When using multiple fonts on a TMP, including fallback fonts, glyphs using fonts other than the primary font are rendered with SubMesh objects. Since these are separated UI elements, they need their own True Shadow component.
Tip
You can make these objects visible under Project Settings > TextMesh Pro > Settings > Hide Sub Text Objects
. If this setting doesn't exist, they should already be visible.
Static text
For texts that don't changes at runtime, you can use the Copy to Sub-Meshes button in the inspector to apply the shadow from the main TMP on any submeshes to preview changes in the inspector. At the start, this is also done automatically.
Dynamic text
If the text are dynamically changed at runtime, some code are neccesarry. These submesh objects don't send the usual dirty signals like other UIs, so True Shadow can't detect when they're changed without expensive polling. When you change these submeshes, you need to call TrueShadow.CopyToTMPSubMeshes()
to update the shadow on the submeshes.
Since the submeshes are not generated until Canvas.willRenderCanvases
, you likely have to delay calling this function:
using UnityEngine;
using LeTai.TrueShadow;
public class ChangeLocalizedText : MonoBehaviour
{
private TMPro.TextMeshProUGUI tmp;
private TrueShadow trueShadow;
private void Awake()
{
tmp = GetComponent<TMPro.TextMeshProUGUI>();
trueShadow = GetComponent<TrueShadow>();
}
void Start()
{
Canvas.willRenderCanvases += OnWillRenderCanvases;
}
bool needUpdateTMPSubmeshesShadow = false;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
tmp.text = Time.frameCount;
needUpdateTMPSubmeshesShadow = true;
}
}
void OnWillRenderCanvases()
{
if (needUpdateTMPSubmeshesShadow)
{
needUpdateTMPSubmeshesShadow = false;
trueShadow.CopyToTMPSubMeshes();
}
}
}
Still doesn't work?
When no longer in use, the submesh objects are hidden using CanvasRenderer.SetMesh(null). Before Unity 2022.2, there is no way to detect this. Thus, in those versions, you need to destroy the objects to get their shadow to disappear. They will be regenerated by TMP when needed.
...
if (Input.GetMouseButtonDown(0))
{
tmp.text = Time.frameCount;
// Needed before Unity 2022.2
var submeshes = GetComponentsInChildren<TMPro.TMP_SubMeshUI>();
for (var i = 0; i < submeshes.Length; i++)
{
Destroy(submeshes[i].gameObject);
}
needUpdateTMPSubmeshesShadow = true;
}
...