The Evil has been defeated - TMPro Glyph Weirdness Be-Gone!


UPDATE: textInfo.character count does NOT encode the visible glyph count - you have to manually count them using .isVisible on each textInfo.characterInfo[] element later.

At long last.

I'm (99% sure) that I have conquered a bug that has been plaguing this project. The bug in question is none other than the text-display-glyph weirdness that only sometimes occurred when text scrolled during dialog. Glyphs would be scaled weirdly, or would be showing the wrong text chars, and getting this to occur consistent was difficult.

The old code looked something like this:


I have a class called PerCharOps which is a container for functions that can be used to animate text on TextMeshPro components. It generically supports the ability to handle stuff like masking/hiding chars in order to implement scrolling text with proper endline handling, as well as do stuff like make words wiggle Paper-Mario style. In Warp Soldier, i just use it to implement scrolling text by shrinking the positions of characters to zero according to a function that i give it.

The algorithm to implement this is pretty straightforward:

  1. Check to see if there are vertices on the TextMesh to the transform
  2. If the number of characters on this has changed since the last time i buffered the old mesh attributes, re-read the attributes into the baseAttributes (baseAttr) buffer (in this case the attribute is localPosition, but could be other stuff like color, UVs, etc)
  3. For each copied glyph attribute, transform it accord to the function provided to the PerCharOps object (this is stored in CharTransform and is retrieved via CharTransform.Get())
  4. Apply those attributes to the TextMesh

The problem that blind-sided me for months lied in step 2 - if i re-encountered a string that had the same number of characters as the previous one, the base attributes wouldn't be copied over! In addition to that, there was another counting issue I messed up in the functions that w_GetAttributes variable would store:

The old implementation used characterInformation.Length, which i think refers to the actual number of characters stored in the textField's textinfo. THAT however, is not the quantity I want when animating glyphs - the geometry that actually displays characters from the string. The value i actually wanted, the rendered glyphCount, is stored in textInfo.characterCount.

That crap I figure out via trial-and-error - the TMPro documentation wasn't exactly useful:

bruh

(Incidentally, I suspect that charInfo.isVisible check is no longer necessary if my hypothesis is correct). UPDATE: that check is necessary because characterCount doesn't actually encode glyph-count like i thought it did. AFAICT you need to count them manually using charInfo.isVisible. Also if ur wondering why I'm adding 4 values to the dstBuf, thats because each glyph's data is stored as quads - 4 corners per glyph.

After that fix was implemented, the old WillRenderCanvasUpdate was updated to remove that attribute-count comparison, this was the final correct function implementation:

This does mean that im re-buffering these values every frame, which may not be great if the per-attribute calculation is expensive AND we have a ton of text, but that's an optimization I won't have to deal with any time soon ( '3').

Get Warp Soldier - Nov 2021 Demo

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.