This generates 11 calls and 0.9kb of GC / frame.
I’ve tried other methods like calculating minutes, seconds and milliseconds separately, then building the string, but that has even much poorer results as far as calls and GC goes.
Has anyone a more efficient solution that does not generate GC?
It’s impossible to create a new string and not generate garbage, and TextMeshPro may very well be doing something with the string you assign as well to generate even more garbage. Your best bet is to only update it as frequently as needed – I doubt you need the time updated every single frame?
You can try the ultra-trashy way: Instantiate 60 texts for 0-59 minutes, instantiate 60 for 0-59 seconds, etc. Then enable/disable the combination you need instead of changing the text. I’m not sure how much GC you’d save from it, but at least the string allocation is gone, and probably the text mesh generation is gone. You’ll still get a canvas rebuild I guess? Not too sure :).
You can totally make a new string without allocating.
Well, not a “string” directly, but you can definitely display changing text with numbers and stuff :p.
Just use SetText() on the tmp text. It has specialized handling for floats and supports basic formatting (just decimal digits, that’s all, but it’s enough).
There are multiple overloads for it, take a look.
It 100% does not allocate anything to build the new string.
Another alternative would be using a string builder (however that might allocate some small strings sometimes when dealing with number to text formatting).
Actually came up with something similar, which is perhaps overkill, but works super well.
Made a static array pool of intToStrings from 0 to 99 in awake, and the value of the array is then called via timeSpan.
After generation, no further garbage at runtime, only 1 call.
Here’s the example for seconds (I use the same path for minutes and milliseconds):
Yes creating a string, will always allocate memory and if you want to pass it to any API’s taking string, it will have to be managed memory.
However, there are ways to get around having to allocate a new string every frame just to display the FPS/Time display/Coin counters that you might want to put into the UI. One way is TextMesh Pro’s SetText API
Another is going to take some reflection, unsafe pointers, and other potentially considered hacky ways to reuse one string per UI element that you need to feed with a string.
that won’t allocate anything for the string generation. I also seem to remember that you can null-terminate strings using that apporach, so if you set chars[n] to ‘\0’, no chars from n or later will be displayed.
Turning time into chars and putting them into the correct slots is an exercise left to the reader.