Came across this since I have been trying to do scrolling text and had the same problem. I dug a bit deeper and found there is something we can use for a replacement for GUIStyle.CalcSize… at least for the purposes we need.
textWeWantToDisplay = "this is just some text we want to display";
TextGenerationSettings generationSettings = txt.GetGenerationSettings(txt.rectTransform.rect.size);
float textHeight = txt.cachedTextGeneratorForLayout.GetPreferredHeight(textWeWantToDisplay, generationSettings);
Debug.Log("textHeight: " + textHeight);
Where our Text component is “txt”. This will log the height of what our Text component will be for the given textWeWantToDisplay.
We can use this by constantly checking the height we have displayed to the screen so far before we write each word. After calculating the height with the new word, if we find that the calculated height is bigger then we can insert a ’
’ new line character.
EDIT: Actually just quickly wrote this up now and it works great
Can be improved but it’s a nice start. To use it, when you’re scrolling (or typewriting) your characters, if you detect a space character, " ", you can call doesNextWordWrap(). If it returns true, write a newline instead of a space.
private bool doesNextWordWrap(string textParagraph, string entireTextParagraph, int index) {
string nextWord = getNextWord(entireTextParagraph, index);
TextGenerationSettings generationSettings = txt.GetGenerationSettings(txt.rectTransform.rect.size);
float originalTextHeight = txt.cachedTextGeneratorForLayout.GetPreferredHeight(textParagraph, generationSettings);
float newTextHeight = txt.cachedTextGeneratorForLayout.GetPreferredHeight(textParagraph + nextWord, generationSettings);
if(newTextHeight > originalTextHeight) {
return true;
}
return false;
}
private string getNextWord(string entireTextParagraph, int index) {
string textAfterParagraph = entireTextParagraph.Substring(index + 1);
string[] nextWords = textAfterParagraph.Split(new [] {" "}, System.StringSplitOptions.RemoveEmptyEntries);
if(nextWords.Length > 0) {
return nextWords[0];
}
return "";
}
On another note, I tried using the cachedTextGeneratorForLayout after reading it’s preferredWidth, as @Bunny83 suggested.
txt.text = textWeWantToDisplay;
float discardme = txt.cachedTextGeneratorForLayout.GetPreferredWidth(textWeWantToDisplay, txt.GetGenerationSettings(txt.rectTransform.rect.size));
UILineInfo[] lineInfo = txt.cachedTextGenerator.GetLinesArray();
Debug.Log("line amount: " + lineInfo.Length);
for(int j=0; j<lineInfo.Length; j++) {
Debug.Log("line's character start index: " + lineInfo[j].startCharIdx);
}
txt.text = "";
It was delayed by one, so for example the first time I ran it, it didn’t have any lines. But the next time I called it, it said it had 2 lines, when really I had 3 lines. This repeated, where it always showed the previous value for “textWeWantToDisplay”. I’m sure a solution could be worked out of it, but I think it would be a bit messier because of the delayed value. A shame since knowing the character index makes this much easier, just pop in a new line character before each index.