Reputation: 33
I have a Prefab made of an Image element and a Text element in the Image. Depending on the length of the text, the prefab gets wider or taller. In script, I need to change the text and get the new size (height, width) of the prefab BEFORE using Instantiate(prefab). My problem is that I'm always getting a size of 0, or the size of the original prefab, without the text modification. My script looks like that :
prefab.GetComponent<Text>().text = myNewText; //insert a long text, supposed to make the prefab wider
float newSize = prefab.GetComponent<Image>().preferredWidth // always getting 0 or the original width of the prefab
// do some things with newSize
Instantiate(prefab);
PS : There is no Collider or mesh renderer in my prefab.
I also tried .GetComponent<RectTransform>().sizeDelta
or .GetComponent<RectTransform>().rect.size.y
but I always get 0 or the size of the original prefab, without the longer text.
Upvotes: 0
Views: 2138
Reputation: 90659
The thing is that you will have to wait until the UI has done a refresh so all layout groups etc are up-to-date.
By default
A canvas performs its layout and content generation calculations at the end of a frame, just before rendering, in order to ensure that it's based on all the latest changes that may have happened during that frame.
If you do not want to wait a frame what you will need to use is Canvas.ForceUpdateCanvases
var newInstance = Instantiate(prefab);
newInstance.GetComponent<Text>().text = myNewText;
Canvas.ForceUpdateCanvases();
Debug.Log(newInstance.GetComponent<Text>().preferredWidth);
This can of course be expensive though depending on the complexity and amount of Canvases you have.
If you rather want to wait a frame you would need to use a coroutine and do
StartCoroutine(SpawnRoutine());
...
private IEnuemrator SpawnRoutine()
{
var newInstance = Instantiate(prefab);
newInstance.GetComponent<Text>().text = myNewText;
yield return new WaitForEndOfFrame();
Debug.Log(newInstance.GetComponent<Text>().preferredWidth);
}
Upvotes: 1
Reputation: 133
My solution to this would be: Instantiate the prefab, Set it as inactive in the scene, get the size, modify it as you like, then set it active again. It should look something like this
Gameobject newPrefab = Instantiate(prefab);
newPrefab.SetActive(false);
float newSize = newPrefab.GetComponent<Image>().preferredWidth;
DoStuff();
newPrefab.SetActive(true);
Have not tested this, but I think this is why you are not getting a width before instantiating
Upvotes: 1