This is actually quite a bit harder than I thought but here is my stab at it. First some disclaimers:
Disclaimers
-
This code is more of a ‘proof of
concept’ and probably could be
optimized / improved quite a bit and
isn’t the type of thing you should
really run every frame.
-
There are scenarios in which this code generates similar bad looking text as unity depending on the length of the words in the text / etc. It might be possible to improve this by allowing words to be broken into pieces but for readability I suggest keeping words intact.
Full Test Code
The following code draws two text boxes - the one on the left uses Unity3D standard label the other one uses some code to format the text before drawing. I added a button so that you can toggle between growing / shrinking the labels to see how the word wrap works at various sizes.
![alt text][1]
using UnityEngine;
using System.Collections;
public class TestDraw : MonoBehaviour
{
Vector2 area = new Vector2(275.0f, 200.0f);
bool grow = false;
void OnGUI()
{
// Common content
string testContent = "This is a centered text meant to show my problem regarding centering of text. The problem is that sometimes it looks like this.";
if(!grow) { area.x -= 0.05f; } else { area.x += 0.05f; }
// Bad text alignment
Rect badDisplayArea = new Rect(5.0f, 5.0f, area.x, area.y);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUI.Box(badDisplayArea, "");
GUI.Label(badDisplayArea, testContent);
// Good text alignment
Rect goodDisplayArea = new Rect(area.x + 10.0f, 5.0f, area.x, area.y);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUI.Box(goodDisplayArea, "");
DrawCenteredText(testContent, goodDisplayArea);
// Toggle shrinking / grow
if( GUI.Button(new Rect( 5.0f, area.y + 50.0f, 50.0f, 50.0f), "Toggle
Grow")) { grow = !grow; }
}
// Note this function will only be work inside an OnGUI method or inside of another method used by OnGUI
private void DrawCenteredText(string textToDraw, Rect textArea)
{
// Get the style we are using for the text
GUIStyle getStyle = GUI.skin.GetStyle("Label");
// Store text alignment
TextAnchor storeAlignment = getStyle.alignment;
getStyle.alignment = TextAnchor.MiddleCenter;
// Create the content object to prevent duplicate 'new GUIContent(textToDraw)' calls
GUIContent textContent = new GUIContent(textToDraw);
// Figure out the width of the text without clipping it
float textWidth = getStyle.CalcSize(textContent).x;
// Figure out the height of the text with clipping
float textHeight = getStyle.CalcHeight(textContent, textArea.width);
// Figure out the average line width
float lineCount = (textHeight / getStyle.lineHeight) - 0.25f; // Modify 0.25f for fine tuning
float averageLineWidth = textWidth / lineCount;
// Go through and construct the centered text
string resultText = "";
string centeredLine = "";
float currentLineWidth = 0.0f;
string[] wordsInText = textToDraw.Split(' ');
for(int i = 0; i < wordsInText.Length; i++)
{
float wordSize = getStyle.CalcSize(new GUIContent(wordsInText*)).x;*
-
// Add the line if the word will make it go over*
-
if(currentLineWidth + wordSize > averageLineWidth)*
-
{*
-
// Add the line to the result*
-
resultText += centeredLine + "
";*
_ centeredLine += wordsInText + " ";_
* }*
* // Add the line to the result*
* resultText += centeredLine;*
* // Draw the text*
* GUI.Label(textArea, resultText);*
* // Restore alignment*
* getStyle.alignment = storeAlignment;*
* }*
}
----------
## What Does The Code Do? ##
My approach was to find out how wide text being displayed is along with how many lines the text is being displayed over and then figure out an average line width and add a new line to any line that will be larger than the average line width.
Knowing that the code should be somewhat self explanatory (I hope).
_*[1]: https://dl.dropboxusercontent.com/u/56331222/Comparision.png*_