- Home /
Maintaining Text Size Ratio With Screen
For my Myst-like exploration game, I wanted to have documents (letters, books, etc) that the player could pick up and read. To accomplish this, I made a C# script which parses an XML file containing position, scale, rotation and data information. The script is meant to use this data to populate an empty Canvas object with the corresponding document.
In order to maintain a consistent experience across players with different setups, I made the XML files store ratios for transformation information so that no matter what size screen the game was being played on, the player would see documents the same, without any unintentional misalignment. The example XML looks like this:
<image xpos="0.5" ypos="0.5" width_ratio="1.5" height_to_screen="0.9" zrot="0" texture="oldpaper" />
<text xpos="0.505" ypos="0.45" width_ratio="0.25" height_to_screen="1.9" zrot="0" font="moms_typewriter" fontstyle="normal" fontsize="14" fontlinespace="1" horizalign="left" vertalign="top" color="#000000" text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent imperdiet, justo non interdum varius, dolor velit varius nulla, quis ornare sapien mauris vitae tortor. Maecenas commodo vel velit a dignissim. Suspendisse eleifend, neque nec finibus consectetur, libero metus dignissim nisi, nec luctus quam quam et orci. Nunc venenatis orci imperdiet neque luctus faucibus. In pulvinar mauris ut odio luctus, id dictum dui porttitor. Fusce feugiat lorem ut ipsum aliquet porta. Interdum et malesuada fames ac ante ipsum primis in faucibus. Suspendisse eget eleifend mauris. Quisque blandit lectus vitae orci varius, a dictum odio hendrerit.
Nullam non suscipit purus. Suspendisse et rhoncus felis. Sed condimentum ex metus, pharetra tempor nisi rhoncus rhoncus. Nunc pharetra convallis sem ut tincidunt. Donec consequat pharetra dapibus. Nam id facilisis nulla, sed consequat urna. Nullam placerat ligula lectus, eu pharetra magna imperdiet ac. Nulla sed elit eu massa fringilla bibendum eu ut dui. Sed eget nibh purus. Sed vitae viverra dui.
Duis quis orci eu dolor accumsan rutrum. Phasellus quis est vitae ipsum aliquam fringilla. Aenean suscipit, felis vel hendrerit hendrerit, lectus nunc accumsan mi, vitae finibus tortor ante id est. Curabitur tincidunt cursus neque, in consectetur mauris. Phasellus pulvinar pellentesque elit efficitur iaculis. Aliquam non nulla massa. Mauris ut justo lorem. Mauris vulputate ligula eget mi varius, vitae varius arcu cursus. Pellentesque vel sapien in mi laoreet faucibus. Fusce condimentum finibus odio, vel bibendum tortor lacinia eget. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed lorem arcu, dictum sed enim ac, scelerisque facilisis mauris. Sed euismod congue sapien ut ornare." />
This is my XML-parsing code:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Xml;
public class DocumentXMLParser : MonoBehaviour {
public string Document_XML_ID; // the name of the XML file containing the document info we want
public Canvas targetCanvas; // the canvas we will project the document onto
public Text damn_text_item;
void Start () {
Debug.Log(Screen.width);
Debug.Log(Screen.height);
XmlDocument XML_File = new XmlDocument (); // create a new instance of an XML document parser
XML_File.Load (Application.dataPath + "/Resources/Document XMLs/" + Document_XML_ID + ".xml"); // load the XML document specified by Document_XML_ID
XmlNodeList TextNodeList = XML_File.GetElementsByTagName ("text"); // Put all of the text items from the XML into a list
XmlNodeList ImageNodeList = XML_File.GetElementsByTagName("image"); // Put all of the image items from the XML into a list
foreach (XmlNode imgnode in ImageNodeList) {
float xpos = float.Parse (imgnode.Attributes ["xpos"].Value);
float ypos = float.Parse (imgnode.Attributes ["ypos"].Value);
float percent_width = float.Parse (imgnode.Attributes ["width_ratio"].Value);
float percent_height = float.Parse (imgnode.Attributes ["height_to_screen"].Value);
float zrot = float.Parse (imgnode.Attributes ["zrot"].Value);
string texturename = imgnode.Attributes ["texture"].Value;
GameObject ImageGameObject = new GameObject ();
RawImage rawImage = ImageGameObject.AddComponent<RawImage> ();
Texture texture = (Texture)Resources.Load ("Document XMLs/Textures/" + texturename + "");
rawImage.texture = texture;
// calculating dimensions!
Vector2 imgSize = new Vector2();
float origWidth = texture.width;
float origHeight = texture.height;
float newHeight = (Screen.height * percent_height);
float newWidth = (((newHeight * origWidth) / origHeight)) * percent_width;
imgSize.x = newWidth;
imgSize.y = newHeight;
rawImage.rectTransform.sizeDelta = imgSize;
rawImage.rectTransform.localPosition = new Vector3((xpos * Screen.width), (ypos * Screen.height));
ImageGameObject.transform.SetParent(targetCanvas.transform);
rawImage.rectTransform.anchorMax = new Vector2 (0.5f, 0.5f); // set the anchor point to the center of the canvas
rawImage.rectTransform.anchorMin = new Vector2 (0.5f, 0.5f);
ImageGameObject.transform.Rotate (new Vector3 (0f, 0f, zrot));
}
foreach (XmlNode textnode in TextNodeList) {
float xpos = float.Parse(textnode.Attributes ["xpos"].Value) - 0.5f; // x-position of the text box
float ypos = float.Parse(textnode.Attributes ["ypos"].Value) - 0.5f; // y-position of the text box
float percent_width = float.Parse(textnode.Attributes ["width_ratio"].Value); // width of the text box
float percent_height = float.Parse(textnode.Attributes ["height_to_screen"].Value); // height of the text box
float zrot = float.Parse(textnode.Attributes ["zrot"].Value); // rotation of the text box
int fontsize = int.Parse(textnode.Attributes ["fontsize"].Value); // size of the text in the text box
float fontlinespace = float.Parse(textnode.Attributes ["fontlinespace"].Value); // line-spacing in the text box
string fontname = textnode.Attributes ["font"].Value; // font used for the text in the text box
string fontstyle = textnode.Attributes ["fontstyle"].Value; // font style (regular, bold, italic, bold + italic) used in the text box as default
string horizalign = textnode.Attributes ["horizalign"].Value; // horizontal alignment (left, center, right) of the text in the text box
string vertalign = textnode.Attributes ["vertalign"].Value; // vertical alignment (top, center, bottom) of the text in the text box
string color = textnode.Attributes ["color"].Value; // color of the text in the text box
string text = textnode.Attributes ["text"].Value; // content of the text box
GameObject TextGameObject = new GameObject (); // create a new GameObject to put our text in
Text TextComponent = TextGameObject.AddComponent<Text> (); // create the actual Text component!
TextGameObject.transform.SetParent(targetCanvas.transform); // make the text box a child of the target canvas
TextComponent.rectTransform.sizeDelta = new Vector2 (((Screen.height * percent_height) * percent_width), ((Screen.width * percent_width) * percent_height)); // set the text box's width and height
Vector3 pos = new Vector3 ((xpos * Screen.width), (ypos * Screen.height), 0f); // create a Vector3 to represent the text box's position
TextComponent.rectTransform.localPosition = pos; // set the text box's position
TextGameObject.transform.Rotate (new Vector3 (0f, 0f, zrot)); // rotate the text box
TextComponent.rectTransform.anchorMax = new Vector2 (0.5f, 0.5f); // set the anchor point to the center of the canvas
TextComponent.rectTransform.anchorMin = new Vector2 (0.5f, 0.5f);
TextComponent.supportRichText = true; // we want rich text!
TextComponent.text = text; // set the text
int origScreenWidth = 1678;
fontsize = ((fontsize * Screen.width) / origScreenWidth);
TextComponent.fontSize = fontsize; // set the text size
//fontlinespace = ((fontlinespace * Screen.width) / origScreenWidth);
TextComponent.lineSpacing = fontlinespace; // set the text line spacing
//TextComponent.resizeTextForBestFit = true;
Color col;
ColorUtility.TryParseHtmlString (color, out col);
TextComponent.color = col;
Font font = (Font)Resources.Load ("Document XMLs/Fonts/" + fontname + ""); // load the font specified
TextComponent.font = font; // set the text to the font specified
if (fontstyle == "normal") { // set font style
TextComponent.fontStyle = FontStyle.Normal;
} else if (fontstyle == "bold") {
TextComponent.fontStyle = FontStyle.Bold;
} else if (fontstyle == "italic") {
TextComponent.fontStyle = FontStyle.Italic;
} else if (fontstyle == "bolditalic") {
TextComponent.fontStyle = FontStyle.BoldAndItalic;
}
if (horizalign == "center") { // bunch of stuff for centering text correctly
if (vertalign == "top") {
TextComponent.alignment = TextAnchor.UpperCenter;
} else if (vertalign == "center") {
TextComponent.alignment = TextAnchor.MiddleCenter;
} else if (vertalign == "bottom") {
TextComponent.alignment = TextAnchor.LowerCenter;
}
} else if (horizalign == "left") {
if (vertalign == "top") {
TextComponent.alignment = TextAnchor.UpperLeft;
} else if (vertalign == "center") {
TextComponent.alignment = TextAnchor.MiddleLeft;
} else if (vertalign == "bottom") {
TextComponent.alignment = TextAnchor.LowerLeft;
}
} else if (horizalign == "right") {
if (vertalign == "top") {
TextComponent.alignment = TextAnchor.UpperRight;
} else if (vertalign == "center") {
TextComponent.alignment = TextAnchor.MiddleRight;
} else if (vertalign == "bottom") {
TextComponent.alignment = TextAnchor.LowerRight;
}
}
}
targetCanvas.gameObject.SetActive(false);
GameObject exitGO = new GameObject();
Button exitButton = exitGO.AddComponent<Button>();
}
public void Trigger() {
targetCanvas.gameObject.SetActive(true);
}
}
This system seems to work well for images at this point, but I am having trouble getting text objects to cooperate. Although the width and height seem to maintain their proportions, I can't figure out how to get the font size to scale so that the text on a paper texture always looks like it is printed at the same size relative to the paper.
Not Maximized: http://imgur.com/VkFpVlw
Maximized: http://imgur.com/hM6Ehiz
I've looked online and haven't been able to find anything that has helped (I have my Canvas scale type set to "Scale with Screen Size" - although this helps, the text is still visibly different between screen sizes.)
TL;DR: Does anyone know of a way to dynamically scale UI text so that it maintains identical wrapping and size relative to the screen?
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
if statement not working for user input 0 Answers
Distribute terrain in zones 3 Answers
Quick Question on UI Text Alignment 1 Answer
Positions of UI Text characters. 0 Answers