반응형

유니티에서 이런 UI를 구현하고자 한다

원리는 간단하다.

탭은 각 UI를 할당하고 있고,

탭버튼을 누를때 다른 종속된 모든UI를 꺼지게하고

내가 누른 버튼에 할당된 UI만 띄우게 하면된다.

결국 각 오브젝트들이 껐다 켜지면서 전환되는 개념이다.
실제 윈도우폼에서의 탭 작동과도 원리가 유사하다

 

 

2개의 cs파일로 간단하게 끝낼 수 있다.

 

기능이 동작하는 방식을 이해하기 쉽도록 아주 간단한 코드로 작성했다

TabButton.cs - 탭 버튼

using UnityEngine.UI;
using UnityEngine;

[RequireComponent(typeof(Button))] //버튼이 없는 오브젝트라면 자동으로 추가
public class TabButton : MonoBehaviour
{
    //해당 버튼 클릭시 열어 줄 UI를 인스펙터창에서 받아온다
    [SerializeField] GameObject panel;
    Image btnImage; //버튼 이미지 
    public GameObject GetPanel => panel;

    TabController parent; //부모 컨트롤러
    private void Start()
    {
        Button btn = GetComponent<Button>();
        btn.onClick.AddListener(SwitchTab); //버튼 리스너에 함수를 할당
        parent = transform.parent.GetComponent<TabController>(); //TabController컴포넌트를 보유한 부모를 가져옴
        btnImage = btn.image; //버튼에 할당된 이미지를 가져옴
    }
    void SwitchTab() //버튼 클릭시 부모에게 내가 눌려졌음을 알림
    {
        parent.SwitchTab(this);
    }
    public void ChangeButtonImage(Sprite _sprite)
    {
        if (btnImage == null) return;
        if (btnImage.sprite != _sprite) //현재 버튼 이미지의 스프라이트와 매개변수 _sprite가 다르다면
            btnImage.sprite = _sprite; //_sprite로 버튼 이미지를 바꿈
    }
}

 

 

TabController.cs - 탭들을 관리하는 관리자 역할

using UnityEngine;

public class TabController : MonoBehaviour
{
    [SerializeField] Sprite btnNormal; //탭버튼이 정상일때
    [SerializeField] Sprite btnSelect; //탭버튼이 눌러진 상태일때

    TabButton[] tabs; //자식들인 탭버튼을 저장할 배열

    // Start is called before the first frame update
    void Start()
    {
        tabs = GetComponentsInChildren<TabButton>();
        SwitchTab(tabs[0]); //첫번째 탭을 눌러준다
    }
    public void SwitchTab(TabButton _target)
    {
        for (int i = 0; i < tabs.Length; i++)
        {
            bool _isActiveTab = _target == tabs[i]; //tabs[i]가 눌려진 버튼인지 판단
            tabs[i].GetPanel.SetActive(_isActiveTab); //모든 탭을 다 꺼준다
            //삼항연산자로 버튼이 눌러졌을때와 일반적인상태일때를 판단해 바꾸어 준다
            tabs[i].ChangeButtonImage(_isActiveTab? btnSelect : btnNormal); 

        }
    }
}

 

두개의 스크립트를 만들고 하이어라키창을 아래와 같이 구성해준다(당연히 입맛대로 설정해주면 된다)

pTabs에는 TabController.cs / 각 탭 버튼에는 TabButton.cs를 넣어주자
아마 TabButton을 넣어주면 버튼이 없을경우 자동으로 생성될 것이다.
해당 버튼이 눌러졌을때 열리게할 패널을 Panel 변수에 넣어주자.

 

모든 탭버튼에 열리게할 패널을 하나씩 각각 넣어주면 버튼쪽은 준비 끝

 

pTabs에는 TabController를 넣어주었다

버튼들의 부모가 되는 pTabs에

BtnNormal, BtnSelect 두개의 스프라이트를 채워넣자.

버튼이 일반적인 상태일때는 BtnNormal의 이미지가 보여질것이고

버튼이 눌려진 상태일때는 BtnSelect 의 이미지가 보여질것이다.

(난 대충 아무거나 넣었다.)

 

pPanels와 그 아래 panel0, panel1 자식들은 UI아무렇게 가져다 꾸몄다.

예시를 위해 바로 보이게끔 0에는 빨강 / 1에는 파랑의 이미지를 넣었다.

대충 이런모양? 아래UI는 원하는대로 필요한 것을 넣으면 된다

 

여러 UI에 탭버튼을 활용해야할때마다 언제든지 갖다 쓰면 될듯하다.

실제로 바로사용해도 무방하나, 프로젝트 상황에 맞게 입맛대로 변경하면 되지싶다.

 

 

퍼가고 맘대로 사용해도 되지만 출처는 꼭 밝히시길..

이해하는데 도움이 되셨다면 아래 하트 부탁함다.

반응형
반응형

 

게임 개발은 객체 생성과 관리가 핵심적인 역할을 합니다. 이를 효율적으로 다루기 위해 Factory 패턴은 유니티(Unity)에서 강력한 디자인 패턴 중 하나로 사용됩니다. Factory 패턴은 게임 오브젝트나 컴포넌트 등의 생성과 관리를 추상화하여 코드의 가독성, 유지보수성, 그리고 재사용성을 향상시키는 데 도움을 주는 패턴입니다.

Factory 패턴이란?

Factory 패턴은 객체 생성 로직을 별도의 클래스로 분리하는 디자인 패턴입니다. 이를 통해 개체 생성에 대한 세부 사항을 숨기고, 클라이언트 코드가 생성 프로세스를 알 필요 없이 객체를 생성할 수 있게 됩니다. Factory 패턴은 크게 두 가지 형태로 나뉩니다.

  • 단순 팩토리(Simple Factory) 객체 생성을 위한 인터페이스를 제공하고, 클라이언트에게 어떤 클래스를 생성할 것인지 선택하는 책임을 지게 합니다. 유니티에서는 이 패턴을 자주 사용합니다.
  • 추상 팩토리(Abstract Factory) 여러 종류의 관련된 객체를 생성하며, 이러한 객체들이 함께 작동할 수 있도록 보장합니다. 일반적으로 복잡한 시스템에서 사용됩니다.

 

햄버거 가게를 상상해보세요. 햄버거 가게는 다양한 종류의 햄버거를 만듭니다. 이 가게에서는 각 햄버거를 주문할 때마다 주문한 종류에 따라 조리과정이 달라집니다. Factory 패턴을 사용하여 이 가게의 동작을 설명해보겠습니다.
햄버거 공장 (Hamburger Factory) 이 공장은 다양한 종류의 햄버거를 만들어내는 곳입니다. 이 팩토리는 주문받은 햄버거의 종류에 따라 다른 햄버거를 생성합니다.
햄버거 (Hamburger) 각각의 햄버거는 고유한 레시피와 재료를 가지고 있습니다. 팩토리는 이 햄버거를 만들 때 필요한 재료와 조리 방법을 알고 있습니다.
주문 (Order) 고객이 원하는 햄버거 종류를 주문합니다. 예를 들어, "치즈버거 주세요" 라고 주문하면, 팩토리는 치즈버거를 만들어 제공합니다.
서비스 (Service) 팩토리는 주문을 받고, 그에 맞는 햄버거를 만들어내며, 최종적으로 손님에게 제공합니다.

Factory 패턴을 사용하면 고객은 어떤 햄버거가 만들어지는지, 어떤 재료와 레시피가 사용되는지 신경 쓸 필요 없이 주문만 하면 됩니다. 팩토리가 주문에 따라 올바른 햄버거를 만들어주기 때문입니다.

이런 방식으로 Factory 패턴은 객체를 생성하고 초기화하는 복잡한 작업을 추상화하며, 클라이언트가 생성 과정을 신경 쓰지 않고 필요한 객체를 얻을 수 있도록 도와줍니다.

 

Factory 패턴의 장점

  • 유연성: 객체 생성 방법을 중앙에서 관리하므로 생성 로직 변경 시 코드 수정이 최소화됩니다.
  • 유지보수성: 객체 생성 코드가 중앙 집중화되므로 유지보수가 쉬워집니다.
  • 재사용성: 객체 생성 로직을 재사용 가능한 컴포넌트로 만들어 코드의 재사용성을 향상시킵니다.

 

Factory 패턴 간단한 실 예제

게임에서 캐릭터를 생성해야 한다고 가정해봅시다. 캐릭터의 생성은 다양한 속성과 초기화 과정이 포함될 수 있습니다.

using UnityEngine;

public class CharacterFactory : MonoBehaviour
{
    public GameObject playerPrefab; // 플레이어 프리팹을 할당할 변수
    public GameObject enemyPrefab;  // 적 캐릭터 프리팹을 할당할 변수

    // 플레이어 캐릭터를 생성하는 메서드
    public GameObject CreatePlayer(Vector3 position)
    {
        GameObject player = Instantiate(playerPrefab, position, Quaternion.identity);
        return player;
    }

    // 적 캐릭터를 생성하는 메서드
    public GameObject CreateEnemy(Vector3 position)
    {
        GameObject enemy = Instantiate(enemyPrefab, position, Quaternion.identity);
        return enemy;
    }
}

 

위의 코드에서 CharacterFactory 클래스는 플레이어와 적 캐릭터를 생성하는 두 가지 메서드를 제공합니다. 클라이언트는 이 팩토리 클래스를 사용하여 필요한 캐릭터를 생성하고 초기화할 수 있습니다.

using UnityEngine;

public class CharacterSpawner : MonoBehaviour
{
    public CharacterFactory characterFactory; // 팩토리 클래스를 할당할 변수

    void Start()
    {
        // 플레이어 생성
        GameObject player = characterFactory.CreatePlayer(new Vector3(0, 0, 0));
        
        // 적 생성
        GameObject enemy = characterFactory.CreateEnemy(new Vector3(5, 0, 0));
    }
}

 

위의 CharacterSpawner 스크립트에서 CharacterFactory 클래스를 사용하여 플레이어와 적을 생성할 수 있습니다.

 

이 예제 외에도

총알을 발사하는 과정에서 총알마다 각기 다른 사거리, 속도, 데미지 등을 설정하고

필요한 상황에 맞게 어떤 총알을 생성하여 어떻게 발사할지 관리하게 만들 수도 있겠죠.

마치며

Factory 패턴을 이용하면 게임 오브젝트 생성과 관리를 효율적으로 다룰 수 있으며, 복잡한 게임에서 객체 생성과 초기화를 효과적으로 관리할 수 있습니다. Factory 패턴은 유니티 프로젝트에서 객체 생성과 관리에 있어서 필수적인 디자인 패턴 중 하나입니다.

 

이런 Factroy 패턴으로 코드를 작성한다면 생성하는 부분과 관리하는 부분을 별도로 가지고있기에 오류가 생길 확률이 적어집니다.

또한, 오브젝트 풀링과도 많은 연관이 있기에 잘 이용한다면 관리가 쉬운 코드를 짤수있습니다.

반응형
반응형

파인만 학습법을 통해 습득한 지식은 몇 분만 투자하여도 한 개념을 깊이 이해할 수 있고, 오랜 기간 기억에 남습니다

 

"어떤 것을 이해하고있다" = "누군가에게 쉽게 설명이 가능하다"

 

Richard_Feynman_1988 - wikimedia

리처드 파인만(Richard Feynman)

리처드 파인만(1918년 - 1988년)은 미국의 물리학자로, 양자 전자동학, 양자 역학, 양자 전자학을 포함한 다양한 물리학 분야에서 기여한 과학자 중 하나입니다. 그의 기여로 인해 그는 1965년에 노벨 물리학상을 수상하였습니다. 파인만은 물리학 연구뿐만 아니라, 학습과 가르침의 분야에서도 혁신적인 방법을 개발했습니다.

 

 

 

 

"어떤 개념을 쉽게 설명하지 못한다면, 제대로 이해하지 못한 것이다"

 

파인만 학습법

파인만 학습법은 리처드 파인만이 자신의 학습과 가르침 방법을 설명한 개념입니다.

 이 방법은 어떤 주제를 깊이 있게 이해하고 다른 사람에게 가르칠 때 사용하는 효과적인 전략을 제시합니다.

다른 사람에게 가르친다는 것은 본인이 제대로 이해하고 있지 않다면, 설명할 수 없는 일이죠.

 

파인만 학습법의 핵심 방법은 아주 간단명료합니다.

 

1. 간단한 언어로 설명하기

파인만은 어떤 주제를 이해하려면 그 주제를 다른 사람에게 가르치는 것이 가장 좋은 방법이라고 믿었습니다.그는 어떤 개념이나 주제를 다른 사람에게 설명할 때, 가능한 간단하고 일상적인 언어를 사용하려 노력했습니다.

2. 콘셉트 맵(Checklist Technique) 사용

파인만은 콘셉트 맵을 사용 하여 복잡한 주제를 시각적으로 정리하고 구조화했습니다.

이를 통해 주제 간의 관계를 이해하고 기억하기 쉽게 만들었습니다.

3. "무엇을 모르는지 알기" 강조

파인만은 학습하는 과정에서 자신이 무엇을 모르는지 인식하는 것의 중요성을 강조했습니다.

이를 통해 부족한 지식을 파악하고 보완할 수 있게 되었습니다.

4. 비판적 사고와 질문

파인만은 항상 비판적으로 사고하고 질문하는 습관을 가지려 노력했습니다.

그는 지식을 받아들이지 않고 항상 왜 그런지를 질문하며 더 깊이 파고들었습니다.

 

 

좀 더 쉽게 설명해 보겠습니다

1. 학습한다.
2. 노트에 주제로 해당 개념을 적는다.
3. 간단한 언어로 설명하기
- 해당 개념을 아예 모르는 사람에게 (혹은 나 자신에게) 가르친다 생각하고 해당 개념을 써 내려가본다.
※ 아이에게 설명한다고 생각하고 일상적인 언어, 쉬운 단어들로 구성해 봅니다.
4. 무엇을 모르는지 알기
써 내려가다 막힌 부분은 결국 쉬운 단어로 표현이 불가하다는 의미이므로 다시 배우고 다시 정리합니다.

 

예시 1

더보기

예시 1: 파인만 학습법으로 뉴턴의 제3 법칙 이해하기

단계 1: 단순한 언어로 설명하기

뉴턴의 제3 법칙은 "모든 작용에는 반작용이 있다"는 원리입니다. 이것을 단순하게 설명하면, 어떤 물체가 다른 물체에 힘을 가하면, 그 다른 물체도 반대 방향으로 동일한 크기의 힘을 가한다는 것입니다. 이것은 일상생활에서 많은 예시로 설명할 수 있습니다. 예를 들어, 축구공을 차면 공도 역방향으로 움직이는 것처럼 생각할 수 있습니다.

단계 2: 콘셉트 맵 사용하기

이 개념을 시각적으로 정리하려면 컨셉 맵을 사용할 수 있습니다. "뉴턴의 제3 법칙"을 중심에 쓰고 그 주변에 "작용"과 "반작용"이라는 용어를 배치하세요. 그리고 각 용어에 대한 설명을 추가하세요. 이렇게 하면 이해하기 쉽게 정리된 개념을 만들 수 있습니다.

단계 3: 질문과 비판적 사고

뉴턴의 제3 법칙을 이해하면서 "왜 그럴까?"라는 질문을 항상 던지세요. 예를 들어, 왜 물체가 반작용을 만드는 걸까요? 왜 힘이 같고 반대 방향일까요? 이러한 질문을 통해 개념을 깊게 탐구하고 이해할 수 있습니다.

예시 2

더보기

예시 2: 파인만 학습법으로 소수 판별 알고리즘 이해하기

단계 1: 단순한 언어로 설명하기

소수 판별 알고리즘은 어떤 숫자가 소수인지 아닌지를 판별하는 알고리즘입니다. 이 개념을 단순하게 설명하면, 어떤 숫자가 1과 자기 자신만으로 나누어 떨어지면 그 숫자는 소수라고 할 수 있습니다.

단계 2: 컨셉 맵 사용하기

콘셉트 맵을 사용 하여 "소수 판별 알고리즘"을 시각적으로 정리하세요. 중심에 "소수"라고 쓰고 그 주변에 "나누어 떨어지지 않음", "1과 자기 자신만으로 나누어 떨어짐" 등의 용어와 그 개념을 추가하세요.

단계 3: 질문과 비판적 사고

이 알고리즘을 이해하면서 "왜 1과 자기 자신만으로 나누어 떨어지면 소수일까?"와 같은 질문을 던지세요. 소수 판별 알고리즘의 원리와 작동 방식을 깊게 이해할 수 있도록 도와줄 것입니다.

파인만 학습법을 활용하면 어려운 주제도 단순하게 설명하고, 시각적으로 정리하여 더 깊이 이해할 수 있습니다. 질문과 비판적 사고는 항상 중요한 습관입니다. 이러한 방법을 사용하여 다른 사람에게 어떤 주제든지 효과적으로 가르칠 수 있습니다.

 

파인만 학습법의 장점

  • 다른 사람에게 가르친다는 기준을 잡고 학습하기에 주제를 더 깊이 이해하게 됩니다.
  • 간단하고 명확한 언어를 사용하면 주제를 더 쉽게 이해할 수 있습니다.
  • 컨셉 맵을 사용하여 복잡한 주제를 시각적으로 정리하고 기억하기 쉽게 만들 수 있습니다.
  • 비판적 사고와 질문 습관을 통해 지식을 확장하고 개선할 수 있습니다.

 

리처드 파인만의 학습법은 어떤 주제를 깊이 이해하고 다른 사람에게 가르칠 때 유용한 전략을 제공합니다. 이 방법을 사용하면 어려운 주제도 더 쉽게 이해하고, 지식을 더 효과적으로 활용할 수 있습니다. 파인만 학습법은 자기 교육과 학습 습관을 개선하려는 사람들에게 유용한 가이드가 될 것입니다.

반응형
반응형

우리의 감정은 우리 삶에서 중요한 부분을 차지합니다. 그러나 감정을 올바르게 이해하고 다루는 것은 쉽지 않을 수 있습니다. 이번 글에서는 정서적 지능의 개념과 그 중요성을 살펴보고, 감정을 더 잘 다루고 더 나은 삶을 살기 위한 방법에 대해 알아보겠습니다.

 

정서적 지능이란 무엇인가?

정서적 지능은 감정을 인식하고, 이해하며, 효과적으로 관리하는 능력입니다. 이것은 감정이 생활의 일부이며 다른 사람과의 상호 작용에 중요한 역할을 한다는 인식을 포함합니다. 정서적 지능은 다음과 같은 능력을 포함합니다
  • 자기 감정 인식: 자신의 감정을 정확하게 인식하고 이름을 붙일 수 있는 능력.
  • 타인의 감정 인식: 다른 사람의 감정을 이해하고 공감할 수 있는 능력.
  • 감정 관리: 감정을 효과적으로 관리하고 부정적인 감정을 긍정적으로 변화시킬 수 있는 능력.
  • 대인 관계: 감정을 통한 대인관계 구축과 유지에 필요한 능력.

정서적 지능 강화를 위한 방법

  • 자기 감정 인식: 자신의 감정을 더 잘 이해하려면 감정 일기를 쓰는 것이 도움이 됩니다. 매일 감정과 그 원인을 기록해보세요.
  • 타인의 감정 인식: 대화 중에 상대방의 감정을 주의 깊게 듣고 이해하려 노력하세요. 공감은 감정적 연결을 강화시키는 데 도움이 됩니다.
  • 감정 관리: 부정적인 감정이 제어를 벗어나면 깊은 숨을 쉬고, 명상을 통해 감정을 조절하는 연습을 해보세요.
  • 대인 관계: 다른 사람과의 대화에서 감정을 공유하고 듣는 것은 더 강한 대인 관계를 형성하는데 도움이 됩니다.

정서적 지능과 더 나은 삶

정서적 지능을 향상시키면, 더 풍부하고 만족스러운 삶을 살 수 있습니다. 감정을 잘 다루는 능력은 대인 관계, 업무 성과, 정신적 안녕 등 여러 가지 측면에서 긍정적인 영향을 미칩니다. 이러한 능력을 키우는 노력은 우리의 삶을 더 풍요롭게 만들어 줄 것입니다.
반응형
반응형

우리 모두가 어느 순간에나 스트레스와 마주하곤 합니다.
그러나 스트레스를 어떻게 대처하고 관리하는지에 따라 그 영향력이 크게 달라집니다. 이번 글에서는 스트레스와 함께하는 우리의 일상에 대해 이야기하고, 건강한 스트레스 관리의 비밀을 알아보겠습니다.

 

스트레스를 마주하다

A씨는 강한 업무 스트레스로 인해 삶의 질이 떨어지고 있었습니다. 그는 술과 담배로 스트레스를 해소하려 시도했지만, 숙취와 건강 문제로 인해 결국 더 많은 스트레스를 안게 되었습니다. A씨는 다음과 같은 대처 방법을 통해 스트레스를 관리하게 되었습니다

스트레스 관리 계획: A씨는 스트레스 관리 계획을 세웠습니다. 업무와 개인 생활의 균형을 맞추고, 스트레스 원인을 파악했습니다.

건강한 습관: 그는 술과 담배 대신 운동을 즐기고 건강한 식습관을 채택했습니다. 이로써 그의 체력과 정신 건강이 개선되었습니다.

 

정신적인 여정

B씨는 업무 스트레스와 가족 문제로 고민하고 있었습니다. 그녀는 다음과 같은 대처 방법을 통해 스트레스를 관리하게 되었습니다
  • 명상과 심호흡: B씨는 매일 아침 명상과 심호흡 연습을 했습니다. 이를 통해 그녀는 정신적으로 안정감을 느끼고 스트레스를 덜 느끼게 되었습니다.
  • 시간 관리: 업무와 가정 생활을 조화롭게 관리하려 노력했습니다. 중요한 작업을 우선 처리하여 스트레스를 줄이는 데 도움을 주었습니다.

 

건강한 습관의 힘

C씨는 스트레스를 관리하기 위해 건강한 습관을 채택하기로 결심했습니다. 그녀는 다음과 같은 대처 방법을 통해 스트레스를 관리하게 되었습니다
  • 운동 및 식사 습관: C씨는 매일 조깅과 건강한 식사 습관을 형성하였습니다. 이로써 그녀는 체력이 향상되고 스트레스를 효과적으로 관리하게 되었습니다.
  • 긍정적인 마인드셋: 긍정적인 마인드셋을 갖추는 노력을 통해 C씨는 스트레스 상황에서도 긍정적으로 대처할 수 있게 되었습니다.

 

긍정의 발견: 우리의 여정

스트레스는 우리의 삶에서 피할 수 없는 부분입니다. 그러나 이를 긍정적으로 대처하고 관리하는 것은 우리의 선택에 달려 있습니다. 스트레스와 함께하는 여정은 우리에게 자기 이해와 성장의 기회를 제공합니다. 건강한 습관을 채택하고 긍정적 마인드셋을 갖추면, 스트레스가 우리 삶의 불꽃놀이로 변할 것입니다.

 

스트레스를 우리의 동반자로 받아들이고, 그와 함께 성장하는 여정을 계속해나가보세요. 그 결과, 건강하고 행복한 삶을 찾아가실 것입니다.

반응형
반응형
특정 상황에서 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