- Home /
TextMesh wordwrap
I use the TextMesh to show downloaded text content from a source I cannot edit.
Lets take for example apple, this is obviously not my client but it will work for the explanation.
On their website it might say "Next Apple keynote March 7 2012"
Then at a later date it might say "iPad3 now is stores!"
In any case I need this word wrap to support it all, the code goes something like this:
WWW www = new WWW(website);
// wait for download to finish
textMesh.text = www.text;
textMesh.text = WordWrapMe(textMesh.text); // Please?
OR - Is there a better solution to show 3D text content?
Answer by shopguy · Sep 21, 2014 at 10:09 PM
I liked Hudi's answer so much I made it in to a reusable class. Just attach to any TextMesh, then set public properties:
UnwrappedText = Set this instead of TextMesh.Text.
MaxWidth = Max width you want to allow
NeedsLayout = Reset to true anytime you modify anything that requires a recalculation to be done (font size, UnwrappedText property, MaxWidth, etc)
ConvertNewLines = Just makes it so you can type \n in the Unity editor to get a new line character.
Edit: I added the BreakPartIfNeeded code because the original version wasn't breaking in the middle of a word if needed, and then it was also causing every word after that to cause a break because the mesh extents were too wide. You can bypass the BreakPartIfNeeded if you are positive you do not need, and you want the code to be more optimized.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(TextMesh))]
public class SmartTextMesh : MonoBehaviour
{
TextMesh TheMesh;
public string UnwrappedText;
public float MaxWidth;
public bool NeedsLayout = true;
public bool ConvertNewLines = false;
void Start()
{
TheMesh = GetComponent<TextMesh>();
if (ConvertNewLines)
UnwrappedText = UnwrappedText.Replace("\\n", System.Environment.NewLine);
}
string BreakPartIfNeeded(string part)
{
string saveText = TheMesh.text;
TheMesh.text = part;
if (TheMesh.renderer.bounds.extents.x > MaxWidth)
{
string remaining = part;
part = "";
while (true)
{
int len;
for (len = 2; len <= remaining.Length; len++)
{
TheMesh.text = remaining.Substring(0, len);
if (TheMesh.renderer.bounds.extents.x > MaxWidth)
{
len--;
break;
}
}
if (len >= remaining.Length)
{
part += remaining;
break;
}
part += remaining.Substring(0, len) + System.Environment.NewLine;
remaining = remaining.Substring(len);
}
part = part.TrimEnd();
}
TheMesh.text = saveText;
return part;
}
void Update()
{
if (!NeedsLayout)
return;
NeedsLayout = false;
if (MaxWidth == 0)
{
TheMesh.text = UnwrappedText;
return;
}
string builder = "";
string text = UnwrappedText;
TheMesh.text = "";
string[] parts = text.Split(' ');
for (int i = 0; i < parts.Length; i++)
{
string part = BreakPartIfNeeded(parts[i]);
TheMesh.text += part + " ";
if (TheMesh.renderer.bounds.extents.x > MaxWidth)
{
TheMesh.text = builder.TrimEnd() + System.Environment.NewLine + part + " ";
}
builder = TheMesh.text;
}
}
}
Replace deprecated property reference
The$$anonymous$$esh.renderer
by
The$$anonymous$$esh.GetComponent<Renderer>()
Answer by hudi · Aug 25, 2014 at 01:24 PM
This came to my mind (it works):
string builder = "";
TextMesh.text = "";
float rowLimit = 1.9f; //find the sweet spot
string text = "This is some text we'll use to demonstrate word wrapping. It would be too easy if a proper wrapping was already implemented in Unity :)";
string[] parts = text.Split(' ');
for (int i = 0; i < parts.Length; i++)
{
Debug.Log(parts[i]);
TextMesh.text += parts[i] + " ";
if (TextMesh.renderer.bounds.extents.x > rowLimit)
{
TextMesh.text = builder.TrimEnd() + System.Environment.NewLine + parts[i] + " ";
}
builder = TextMesh.text;
}
yup it works
(here another way to write the same thing but more readable for me)
protected void fillTextField(string val) {
float rowLimit = 2f; //find the sweet spot
string[] parts = val.Split(' ');
string tmp = "";
txt.text = "";
for (int i = 0; i < parts.Length; i++)
{
tmp = txt.text;
txt.text += parts[i] + " ";
if (txt_render.bounds.extents.x > rowLimit)
{
tmp += Environment.NewLine;
tmp += parts[i] + " ";
txt.text = tmp;
}
}
}
Answer by tingham · Mar 06, 2012 at 12:37 AM
You'll need to encapsulate your text and determine your own line-length unfortunately. From there it's pretty simple though, just insert \n in your text and TextMesh will wrap the line. Each character is going to occupy a certain space in your screen space; and there are a lot of different ways you might measure or break the line. Might be easiest to delimit on the space character and wrap words greedily.
Answer by masha · Dec 16, 2013 at 03:04 PM
You should have a look at those answers =] http://answers.unity3d.com/questions/190800/wrapping-a-textmesh-text.html#answer-597981
Your answer