반응형
특정 상황에서 ContentSizeFitter는 제대로 작동되지 않을 때가 있다.
UI끼리 겹치는 예가 딱 그렇다. (UI끼리 쓸데없이 멀어지기도 한다)
국내 해외 할 것없이 검색해보면 여러 방법들이 있었지만, 그 역시 제대로된 해결법이 아닌듯 했다.

좀 찾아보다가 제대로 작동하는 방법을 찾아서 이런저런 실험을 해보고 
몇가지 주의사항만 잘 참고해서 UI레이아웃 즉시 강제 재설정을 하면 해결된다.

텍스트UI와 이미지UI가 겹친다

우선 예시해결방법을 먼저 보고, 이러한 문제가 일어나는 특정상황에 대해서 설명하겠다.

예시

1. 예시를 위해 스크립트를 작성했다.

using UnityEngine;
using TMPro;
public class Test : MonoBehaviour
{
    [SerializeField] TextMeshProUGUI tText;

    //랜덤으로 가져 올 아이템 이름들
    string[] itemName = new string[] { "루비", "가짜보석", "빨갛게빛나는보석" };

    //텍스트를 변경하는 함수
    public void ChangeText()
    {
        //itemName 배열에 있는 string을 랜덤으로 하나 가져온다.
        int rand = Random.Range(0, itemName.Length);
        //랜덤으로 가져온 itemName과 함께 텍스트를 바꾼다
        tText.text = $"아이템 \'{itemName[rand]}\' 획득하였습니다!";
    }
}

2. 작성한 스크립트를 저장하고 스크립트를 오브젝트에 추가했다.

작성한 스크립트를 상위 Canvas에 추가했다.

 

그리고 Panel_Toast에 버튼을 만들어 주었고 

버튼을 눌러 ChangeText() 함수를 실행하면 itemName 배열에 담긴 아이템 이름 중 하나를 랜덤으로 뽑아 텍스트를 바꾼다.

예를 더 잘보여주기 위해 일부러 itemName은 글자 수가 다 다르게 지정했다.

 

각 오브젝트는 간단한 작업이지만 초보분들을 위해서 상세하게 설명하였다.

이글을 유심히 읽으시는 독자분이시라면 이미 하드하게 작업하다가 막혀서 오셨을테지만..

 

 

이제 실행을 해서 메시지를 눌러보면 바로 겹쳐버린다.

글자 길이가 가장 길게 나온 뒤 바로 다음 작은 글자수가 나오게되어도 마찬가지로 변화가 없다.

글자 수가 작은 것도 사이즈가 변경되지 않는걸로 보아 제대로 작동하지 않는다

해결법

자, 이문제를 해결할 함수는 ForceRebuildLayoutImmediate(UI레이아웃 즉시 강제 재설정) 이다.

using UnityEngine;
using TMPro;
using UnityEngine.UI;

public class Test : MonoBehaviour
{
    [SerializeField] TextMeshProUGUI tText;

    //랜덤으로 가져 올 아이템 이름들
    string[] itemName = new string[] { "루비", "가짜보석", "빨갛게빛나는보석" };

    //텍스트를 변경하는 함수
    public void ChangeText()
    {
        //itemName 배열에 있는 string을 랜덤으로 하나 가져온다.
        int rand = Random.Range(0, itemName.Length);
        //랜덤으로 가져온 itemName과 함께 텍스트를 바꾼다
        tText.text = $"아이템 \'{itemName[rand]}\' 획득하였습니다!";

        ///지금은 텍스트지만
        ///ContentSizeFitter가 적용되어 사이즈가 변경되는 UI의 RectTransform을 넣어주면 된.
        LayoutRebuilder.ForceRebuildLayoutImmediate(tText.rectTransform);
    }
}
 LayoutRebuilder.ForceRebuildLayoutImmediate( 타겟RectTransform );

저 한줄을 입력하고 실행해보면

잘 나온다.

 

이 외 검색을 해보면 다양한 방법들이 있는데, 

코루틴을 사용해서 리프레시를 한다던지,

LayoutGroup내 Control Child size 매개변수를 건드린다던가..(매개변수를 꺼주어도 안되는 상황이 있다.)

꼼수에 가깝거나 좀 지저분한 방법들이 많았다.

 

 

해당 문제가 일어나는 특정상황

우선 작동이 안되는 '특정상황'이란 이런 것이다.

1. 부모 오브젝트에 ContentSizeFitter가 있고, 하위오브젝트에도 ContentSizeFitter가 중복으로 있을 때
2. 혹은 서로 연관된 UI오브젝트가 각자 ContentSizeFitter 컴포넌트를 가지고 있을때다.

즉, ContentSizeFitter가 공통된 레이아웃 안 여러 곳에 있을 경우 발생한다.

이럴 경우,

결국 ContentSizeFitter가 작동하는 순서가 얽혀서,

가장 마지막에 작동하는 ContentSizeFitter에 의해 겹치거나 멀어지는 결과를 가져온다

즉 UI그리는 과정에서 순서가 꼬여서 생긴 문제이다.

 

그래서 다음 프레임에 다시 재설정하게 하는 것도 어찌보면 방법인셈.

 

주의사항 -  안되는 경우

간단하게 설명할 수도 있었지만 이렇게 원리까지 디테일하게 설명한 이유가 여기에있다.

 

ForceRebuildLayoutImmediate 함수로 인해 문제가 해결이 안되는 것은 열에 아홉은

해당 오브젝트가 activeSelf 가 false인 상태에서 호출을 하고 이후 SetActive(true); 를 했을 경우다.

예를들어

//액티브가 꺼져있는 상태로 강제로 재설정을 한다한들 결국 다시 true가 되었을 때 UI를 다시 그린다
//즉 ForceRebuildLayoutImmediate를 기입한 이유가 없어진다.

tName.SetActive(false);//어떠한 이유로 오브젝트를 꺼놓았다

LayoutRebuilder.ForceRebuildLayoutImmediate(tName.rectTransform);//UI레이아웃 즉시 강제 재설정

tName.SetActive(true); //오브젝트를 다시 켠다.

위처럼 사이즈 조절에 문제가 있는 레이아웃에 연관된 오브젝트가 꺼져있는 상황에서 백날 강제로 레이아웃을 재설정해도 반응이 없다.

(재정렬하려는 오브젝트의 active가 true가 되었을때 다시 리셋되기때문인지, false일때 작동을 안하는 건지는 확실치 않지만..)

 

해당 부분만 잘 인지하고 사용하면 문제 없이 작동한다

반응형

+ Recent posts