I’m using the technique described on this page: » Eureka! Garbage-free string manipulation in Unity!Defective Studios Devblog to allow me use garbage free string manipulation in Unity.
Briefly, I create a stringbuilder and use reflection to grab the internal string from it. I can then modify that string using stringbuilder.append() etc and simply pass the previously extracted string reference to wherever it’s needed without needing to call ToString() on the stringbuilder object. For testing purposes, I’m incrementing a number in Update and appending the value to the previously described string.
The problem is, short of enabling and disabling either the Canvas or Text component of the canvas object, there doesn’t seem to be a way to force the UI to invalidate and redraw itself via code, I’m assuming this is because I’m reassigning the same string reference to the Text component whenever I need to change it and Unity assumes it hasn’t changed. I can see the change to the string is reflected immediately in the Inspector window (also confirmed it in the debugger) however the actual text object in game is not redrawn unless I force Unity to redraw it via enabling/re-enabling the Text component, which doesn’t seem like an efficient way of doing it. The article suggests tricking the system into updating the text via first setting it to some other value, “” for example, however this doesn’t work with the new UI system. Is there any way I can get this system to work with the new UI without having to disable and re-enable the component whenever I change the value in the string? The relevant code is below:
string myScoreString;
public Text scoreText; //scoreText is the Text component of the canvas I want to change
private StringBuilder sbScore;
int PlayerScore = 0;
public static string GetInnerString(this StringBuilder sb)
{
string str = (string)sb.GetType().GetField(
"_str",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance).GetValue(sb);
//Optional: clear out the string
for (int i = 0; i < sb.Capacity; i++)
{
sb.Append(" ");
}
sb.Length = 0;
return str;
}
void Start () {
sbScore = new StringBuilder(32, 32);
myScoreString = sbScore.GetInnerString(); //string reference acquired from stringbuilder
}
void Update () {
PlayerScore++;
//update the string via the stringbuilder
sbScore.Length = 0;
sbScore.Append(PlayerScore);
scoreText.text = "";
scoreText.text = myScoreString; //assign the string to the Text component
}