inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진

UI Manager #1

UI_Button 클론이 무한생성

해결된 질문

307

몽몽이 바보다옹~

작성한 질문수 7

0

 

UI_Button 클론이 무한생성됩니다.



public class Test : MonoBehaviour
{
    GameObject er;


    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Managers.UI.ShowPopupUI<UI_Button>();
        }
    }
}

아래 코드로 문제가 있어서 화면을 클릭했을 때만 팝업이 뜨도록 위의 코드로 Test 스크립트를 일부 바꿔 봤습니다.

그러고나서 보니까

public static UIManager UI{get{return instance._ui;}} 이 지점에서 계속 다시 Test 파일의

if (Input.GetMouseButtonDown(0)) { Managers.UI.ShowPopupUI<UI_Button>(); }

이 부분으로 가는 것 같습니다. 늘어나는 갯수로 처음엔 한번 클릭했을 때는 한번으로 잘 늘어나는데 그 다음엔 2개가 생기고 그 다음엔 5개..? 규칙을 알 수 없게 늘어납니다

저 요즘 질문 너무 많이하죠..ㅜㅜ 그치만 미워하지 말아주세요 다 기본 3시간은 고민고민하며 노려보다가 보내는거긴해유..하핳..

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    GameObject er ;
    void Start()
    {
        Managers.UI.ShowPopupUI<UI_Button>();
    }

    void Update()
    {
        
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ResourceManager
{
    public T Load<T>(string path) where T:Object
    {
        return Resources.Load<T>(path);

    }
    public GameObject Instantiate(string path, Transform parent = null)
    {
        GameObject prefab = Load<GameObject>($"Prefabs/{path}");
        if (prefab == null)
        {
            Debug.Log($"Failed to load prefab : {path}");
            return null;
        }
        return Object.Instantiate(prefab, parent);//Object붙이는 이유는 리소스메니저에 있는 Instantiate를 또 호출하려고 할까봐.
    }
    public void Destroy(GameObject go)
    {
        if(go == null)
            return;
        
        Object.Destroy(go);

    }
}


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Managers : MonoBehaviour

{
    static Managers s_Instance; //유일성이 보장된다
    static Managers instance { get { Init(); return s_Instance; } } // 유일한 매니저를 갖고온다
    
    ResourceManager _resource = new ResourceManager();
    UIManager _ui = new UIManager();

    public static UIManager UI{get{return instance._ui;}}
    public static ResourceManager Resource{get{return instance._resource;}}
    // Start is called before the first frame update

    void Start()

    {

        Init();
        

    }

    // Update is called once per frame

    void Update()

    {
    }

    static void Init()

    {

        if (s_Instance == null)

        {

            GameObject go = GameObject.Find("@Managers");

            if (go == null)

            {

                go = new GameObject { name = "@Managers" };

                go.AddComponent<Managers>();

            }

            DontDestroyOnLoad(go);

            s_Instance = go.GetComponent<Managers>();

        }

    }



}using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIManager
{
    
    int _order = 0;
    //팝업 목록을 들고있어야함. 스택 구조으로 관리하기 가장 마지막에 띄운 팝업이 가장 먼저 삭제돼야하니까.
    Stack<UI_Popup> _popupStack = new Stack<UI_Popup>();
    public T ShowPopupUI<T>(string name = null) where T : UI_Popup//T에는 UI버튼이라는 스크립트를 건네고 name에는 팝업프리펩을 건네줄거임.
    {
        if(string.IsNullOrEmpty(name))//이름이 비어있으면 T타입의 이름과 똑같은걸로 넣겠다.
            name = typeof(T).Name;

        GameObject go = Managers.Resource.Instantiate($"UI/Popup/{name}");
        T popup = Util.GetOrAddComponent<T>(go);
        _popupStack.Push(popup);
        return popup;
    }

    public void ClosePopupUI()
    {
        if (_popupStack.Count == 0) //stack을 건드릴 떈 항상 카운트를 체크하는걸 습관화하기
            return;

        UI_Popup popup =  _popupStack.Pop();
        Managers.Resource.Destroy(popup.gameObject);
        popup = null;

        _order--;
    }

}



using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Util
{
    public static T GetOrAddComponent<T>(GameObject go) where T : UnityEngine.Component
    {
        T component = go.GetComponent<T>();
        if (component == null)
            component = go.AddComponent<T>();
        return component;
    }
    public static GameObject FindChild(GameObject go, string name = null, bool recursive = false)

    {

        Transform transform = FindChild<Transform>(go, name, recursive);//<Transform>을 사용하면 FindChild 메서드가 호출될 때 해당 메서드는 Transform 타입의 자식을 찾도록 약속됩니다. 이는 제네릭을 사용하여 메서드를 특정 타입에 제한하는 방법 중 하나입니다.

        if (transform == null)
            return null;

        return transform.gameObject;

    }
    public static T FindChild<T>(GameObject go, string name = null, bool recursive = false) where T : UnityEngine.Object
    {
        if (go == null)
            return null;

        if (recursive == false)
        {
            for (int i = 0; i < go.transform.childCount; i++)
            {
                Transform childTransform = go.transform.GetChild(i);

                if (string.IsNullOrEmpty(name) || childTransform.name == name)
                {
                    T component = childTransform.GetComponent<T>();
                    if (component != null)
                        return component;
                }
            }
        }
        else
        {
            foreach (T component in go.GetComponentsInChildren<T>(true))
            {
                if (string.IsNullOrEmpty(name) || component.name == name)
                    return component;
            }
        }

        return null;
    }
}

C# unity

답변 2

0

Rookiss

image
일단 가장 인접한 코드를 다운받아 다른게 없는지 비교해보세요.
사실 질문하신 내용만 보고서는 저도 알 수가 없습니다.
코드와 별개로 GameObject에 어떻게 Component를 붙였는지 또한 관건이기 때문입니다.
요즘 정말 시간이 바빠서 일일히 코드를 봐드릴 수가 없는데요.

문제가 일어날 때 유용한 방법은
- 책 or 강의 코드를 부분적으로 복붙해가며 다른 부분 있는지 범인 색출
- 디버깅 (로그 찍거나, breakpoint 걸어서 멈춰서 보기)
- 코드 분석 (무한 헤딩)

등이 있는데요. 처음엔 고통스럽겠지만
어차피 프로그래머의 업무중에 50% 이상은 버그 찾는 것이라
익숙해지셔야 합니다.

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다.

해당 문제와 관련하여 이전에 다른 수강생이 비슷한 문제를 제기한 사례가 있어 유사한 경우를 찾았습니다. 아래 링크를 통해 비슷한 문제에 대한 강사님의 답변을 참고해보시면 도움이 될 것 같습니다.

도움이 되셨길 바라며, 질문&답변 게시판을 통해 추가적인 질문이 있으시면 언제든지 올려 주시기 바랍니다.

UI 기능 관련 질문이 있습니다!

0

37

2

픽셀 좌표 스크린 좌표

0

33

0

전체적으로 코드 읽는게 굉장히 오래 걸리네요...

0

74

2

카메라 #2 수업 캐릭터 쓰러짐 해결

0

84

1

플레이어 움직임이 끝날때, 기울어짐 현상

0

83

1

Input 적용과 관련하여 질문 있습니다.

0

75

1

디버그 불가.. Unity에 연결 불가

0

82

1

달리기 애니메이션 에러

0

89

2

오랜만에 게임을 만들다가 사운드 관련해서 뭔가 궁금한게 있어서 봤습니다

0

66

1

GetKey 오류

0

109

2

에셋을 어디에 올려두신지 알 수 있나요?

0

107

1

재귀호출? 오류나는데 왜 이래요 ?

0

169

6

Animation blending 파라미터 계산

0

68

1

newPos와 to지점이 겹쳐져야 하는거 아닌가요?

0

97

3

오브젝트 복제하니까 자꾸 이런게 뜨면서 꺼집니다

0

88

2

질문있습니다

0

143

2

아 이거 소스코드 같은거 없나요?

0

142

3

질문 드립니다. string.IsNullOrEmpty(name)

0

87

2

@Managers 가 씬에 배치되어 있어도 문제가 되지 않나요?

0

136

2

유니티6 NavMesh 안되는분들

1

176

1

Unity6 Unity-Chan Material 마젠타 문제 해결법

7

527

1

GetComponent<Poolable> 질문드립니다.

0

102

2

UI 불러오지 못함

0

119

2

UI 자동화 #1 - Util.cs의 FindChild함수에서 component.name에 컴포넌트 이름이 뜹니다.

0

155

2