ui.text character limit

Well, seems that the UI.Text component has vertex limit of 65k.
The new Unity ui uses 20 or 21 vertices per character.
This makes the Text component to crash really easily.
3120 characters is 80x39 its not even typical windows console size.
Why is Unity using so many vertices per characters ? If you look at the wireframe view
each character has mayhem of triangles. ngui had just 2 triangles ( 4 vertices ) and i can’t see the quality
difference.
so how to determine the character limit to safely create new text components or canvases to go around the 65k vertex limit ? the font and language is changing run-time depending of country and localization.

It’s kinda stupid they use geometry to do that instead of render text to texture and display on a quad IMO. Text doesn’t change often, so even with text rendering being cpu bound for that, it wouldn’t be much of performance hit.

So everytime I modify my text at runtime, I have to render it to a quad mesh?
Btw quad mesh are additional drawcalls :stuck_out_tongue:

Wow are you serious, why would you make text geometry?
That doesn’t seem to make any sense imo.

But I guess they had their reasons lol.

This has been driving me crazy. Trying to do a chat window that scrolls and it will break on as few as 40 entries of chat depending on what’s typed. Trying to break text into multiple Text elements doesn’t help much, the vertices limit of the Canvas gets reached.

The workaround seems to be to create multiple Canvas elements. That doesn’t seem reasonable, how’s that going to affect performance? Organizational nightmare too.

UI.Text uses 4 vertices / 2 triangles per character. Now if you add the Outline or Shadow FX, those duplicate geometry which will then increase the vertices count to roughly what you have reported.

The 65535 limit is in fact per Canvas. So when using Outline + Shadow FX, not only is performance not ideal but the geometry limitations comes around really fast.

Alternatively, you could consider using TextMesh Pro where visual FX like Outline & Shadow are done at the shader level and are dynamic. Along with the reduced geometry, this yield a pretty significant performance boost.

Here are the results of a benchmark I ran a few weeks ago which I posted here.

I re-ran these same tests in Unity 5.2.2f1 and the results are the same. Using Text + Outline + Shadow, TextMesh Pro offers more than 10X performance and lower geometry count. Since TMP still uses the Canvas system, it is still subject to the 65535 vertices limits.

P.S. In terms of the geometry limitations, when I have time, I will investigate if I could add an optimization where the geometry for characters that are not visible is not created. By not visible, I mean characters that would be outside the viewable area of a 2D RectMask for instance.

2 Likes

You need to cull what isn’t actually visible. This also is a huge performance gain. If you have ~65k verts showing, it’s going to be huge performance hit in the first place.

When I get around to looking at this, I think it should provide another incremental performance boost for TextMesh Pro over Ui.Text. However, this is not a clear cut thing as having to rebuild the entire geometry each frame comes at a cost. Right now geometry that is not visible is handled by the shader which is efficient.

The primary goal here is to look for ways to provide more flexibility around the 65K vertices limit per Canvas. Even if there was no additional performance gains, having characters that are not visible not count towards the 65K limit would be nice.

Sorry, I was using “cull” in the generic sense, not as in camera culling. You can have much more than 65k verts on a canvas, you just can’t have more than 65k active.

I just came across this same problem and I’m hoping for a potential solution.

I am creating a game that contains a text output window, and I sequentially add text to this as the game progresses. There is enough text being generated during gameplay that it will easily exceed the character/vertex limit. The problem is that I want the player to be able to scroll back through the entire text transcript if desired. This isn’t the kind of problem that can be solved with multiple Canvases, as far as I can tell.

I began using a UI.Text component, and then later switched to TextMesh Pro, but as described above both seem to have the same issue.

Are there any potential solutions for a scrollable text output window that can hold a very (very) long string of text like this?

1 Like

No, Unity would do it for you behind the scenes. Frankly I think it’d be best solution, to have text object only taking 4 verts/2 triangles and when ui text is changed, render it to texture and then display on ui text (it could be done on C++ side of Unity so it’d be very fast, especially when library capable of HW acceleration such as Cairo or Freetype is used).

Even if it takes few miliseconds, it could be a) done in separate thread, b) wouldn’t matter as large amounts of text (which are susceptible of this limit) doesn’t change every frame if at all and small amounts of text that needs to change fast, such as fps counter takes little space so smaller texture can be generated (which is fast).

Additionally, Unity could be smart about it and only employ “rendered texture on quad” method if trying to doing it using current method fails because of the vertex limit.

You need to break it up. Maybe by line breaks or story/action beats or something like that. One long string is hard to manage, and could lead to memory issues.

Then all you have to do is draw them as blocks in your scroll window, and just turn off the ones that are visible on screen. Then turn them in when they are. I would leave thier container on, and just turn off the text element. That way you will keep the height of the scrollable area.

That would be way overkill. It would use a lot of unnecessary resources and would be slow. Since a render texture still requires drawing the ui elements first there isn’t any savings in terms of scrolling. Unless you are suggesting rendering a massive area, but even then, you lose the ability to cull (manually or otherwise) mean you are trading verts which are cheap for texture memory which is expensive.

And threading isn’t going to help. New threads don’t have access to the unity api, so you either have to pass it the rendered data which is pointless, or create a whole subsystem that can take text and render it to a texture, which is redundant. Moreover, the data you get back from the worker thread will still have to be turned back into a unity texture and rendered. Threads aren’t the answer.

The solution is to just not draw stuff out of the camera view. Either breaking into blocks, or being creative with string manipulation. (Though that could be tricky to right/smooth)

No, not the render texture. Just draw text itself on empty Texture2D using FreeType, Cairo or any other text rendering library and then apply it to a quad. As I said, Unity would do that behind the scenes.

You would have set those up as plugins and still have to write layout wrappers/methods that you could pass in all the settings you want, it would return byte data that you would have to apply to a texture2d and make the mesh. It’s a lot of work to make workable. A lot of extra cpu, and and memory, especially texture memory redundant memory at that. Not a good trade off to save mesh, which is cheaper. Especially for the requirements of the op. That way will lead to crashes and performance issues.

I am not sure what you by ‘behind the scenes’. While it may not run on the primary thread, it isn’t free.

Not if it’ll be part of Unity’s core, like physics and audio support.

A simple but quite effective solution: Dynamic, scrolling text support - Unity Engine - Unity Discussions

In short: use one “Text” component per line (or more, up to limit), and use new “RectMask2D” instead of “Mask”. “Vertical Layout Group” and “Content Size Fitter” will help you to place the items correctly. “Layout Element” would be useful to set the minimum height of the item. That’s all. Good enough for large amount of text with scroll support :slight_smile:
My small project to test the idea: GitHub - gresolio/Unity_UiTextLimit: Unity UI.Text component vertex limit

Would an Object Pool help at all?

Just as an FYI, I did add in the latest release of TextMesh Pro a feature where text that exceeds the 65,535 vertices limit is automatically split into sub text objects. From a user’s point of view, this is just a single text object which works like any other text object but happens to contain lots of characters.

I’ll try to build an example scene and do some tests.

1 Like

Yes, it will be very helpful. Especially if you want to show only the last N messages and avoid re-creating game objects.

Thank you for the excellent plugin :slight_smile: Sounds very good, I’m looking forward to try your solution.