Reputation: 65
In my unity application, I need make little rectangular components with a string on them. However, I want the size of the rectangle to dynamically line up to the text inside it. This is the hierarchy in my prefab:
According to this article, I just need to add a content fitter to the canvas. I did that and set both horizontal and vertical sizes to "preferred", however apparently the width is just 0 (0 is getting printed out by my Debug.Log). This is my code. I think the issue might have to do with changing the render mode, but this is for a VR application so that needs to stay:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Script : MonoBehaviour
{
public static string s_text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
public Transform panel;
public GameObject wordPrefab;
private float panelWidth;
private float panelHeight;
// Start is called before the first frame update
void Start()
{
panelWidth = panel.GetComponentInParent<Canvas>().GetComponent<RectTransform>().rect.width;
panelHeight = panel.GetComponentInParent<Canvas>().GetComponent<RectTransform>().rect.height;
Vector3 nextPosition = new Vector3(-panelWidth / 2, panelHeight / 2, 0);
foreach (string word in s_text.Split(' '))
{
GameObject go = Instantiate(wordPrefab, panel, false);
go.GetComponentInChildren<Canvas>().renderMode = RenderMode.WorldSpace;
go.GetComponentInChildren<Text>().text = word;
go.transform.localPosition = nextPosition;
float wordWidth = go.GetComponentInChildren<Canvas>().GetComponent<RectTransform>().rect.width;
Debug.Log(wordWidth); // This is 0 every time when it shouldn't be!
nextPosition = 0; // I will figure this out once I can access the size of the blocks
}
}
// Update is called once per frame
void Update()
{
}
}
TL;DR: I need to get the parent canvas to size correctly, and for some reason its width/height are 0 after doing exactly what the linked article said and using a content fitter.
Upvotes: 1
Views: 2852
Reputation: 6275
I believe this should answer your question - if you have more issues with this implementation, just let me know.
Firstly, remove all code with resizing. Unity's component UI system is very powerful when used properly. Almost anything you would want to achieve with dynamic UI can be done using just components.
Firstly, your container holding the text should have a Horizontal Layout Group
or a Vertical Layout Group
attached to it. Turn off all toggle boxes except for Control Child Size
- Height
. Set the width of this container to whatever you want the width to be, the text will fill to this size.
Along with a layout group (you can choose either one, but as your text is vertical you can use a vertical layout group), you will need a Content Size Fitter
with the Horizontal Fit
set to Unconstrained
and the Vertical Fit
set to Preferred Size
.
It should look something like...
Now moving onto the text component, you can use a Unity.UI.Text
component or a TMPro.TMP_Text
component, either one will work. In this example, I am using the vanilla Unity.UI.Text
. Simply type whatever message you would like in the text field and your parent container should resize to the text field. If you are dynamically setting this text often, you might need to force Unity to rebuild the layout group of your parent object to rescale.
An example snippet of this could look like...
using UnityEngine.UI;
// the text object that is resizable
[SerializeField] private Text dynamicText = null;
// the parent container that holds the text
[SerializeField] private RectTransform dynamicTextParent = null;
public void UpdateTextField(string txt)
{
// assign the new text info
dynamicText.text = txt;
// force Unity to recalculate the UI hierarchy of this object recursively down its child nodes
LayoutRebuilder.ForceRebuildLayoutImmediate(dynamicTextParent);
}
In this example, you would need to assign dynamicTextParent
and dynamicText
in the inspector. There is also a chance that you will not need to forcibly rebuild the UI hierarchy, so test it without first. If you run into issues, add the LayoutRebuilder
under the line where you assign the new text field.
Upvotes: 2