• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

AddComponent와 UI_Popup.cs에 대한 질문

21.04.11 01:04 작성 조회수 329

0

안녕하세요 강의 너무 잘 듣고 있습니다.

강의를 들으면 들을수록 기초 개념이 부족하다는 생각이 듭니다.

1.

이미 되게 자연스럽게 쓰고있던 AddComponent 함수에 대한 질문입니다.

를 실행하면 

ShowPopupUI에 들어가 GetOrAddComponent<UI_Button>(go) 함수를 호출한 셈이 될테고, 만약 go에 UI_Button 컴포넌트가 없다면 Add를 하게 될텐데 Add될 컴포넌트는 UI_Button.cs인가요? 더 궁금한건 실제 Prefabs/UI/Popup 안에도 UI_Button이란 prefab이 존재하는데 Unity가 이 둘을 잘 알아서 구분하나요? (물론 prefab이 컴포넌트로 붙을 수는 없다고 생각하지만 예를 들어 같은 이름의 스크립트 파일이 다른 파일에도 여러개 존재할 수 도 있을텐데 이럴땐 어떻게 구별하나요?)

2. UI_Popup의 init함수에 들어가는 내용이 Start에서 실행되지 않기에 UI_Button.cs의 Start()->Init()->base.Init()를 통해 간접 실행하게 되는데 

UI_Popup에 있는 gameObject가 UI_Button으로 뜨는 이유가 아리송합니다. gameObject가 Component라는 조상클래스의 맴버 변수이며 UI_Button이 UI_Popup을 상속받았기에 가능한 일인가요?

3. ClosePopupUI함수를 virtual 키워드로 작성하신 이유를 알 수 있을까요? UI_Base에서 재정의하여 사용하는 경우가 있나요?

답변 8

·

답변을 작성해보세요.

1

Component(gameObject 변수 소유)<----- ... <-----UI_Base <-----UI_Popup<-----UI_Button

아하, 강의를 만든지 너무 오래돼서 기억이 가물가물했는데
UI_Button이 UI_Popup 상속이었군요 -_- 답변을 정정 드립니다.

결국 UI_Button에서 사용하는 gameObject나 UI_Popup에서 사용하는 gameObject나 UI_Base에서 사용하는 gameObject나 모두 동일한 gameObject아닌가요? 

-> 네 동일합니다. 

gameObject가 Component라는 조상클래스의 맴버 변수이며 UI_Button이 UI_Popup을 상속받았기에 가능한 일인가요?

-> 그러고보니 이 질문도 제가 잘못 이해했네요. UI_Button이 UI_Popup을 상속받은 것 '자체'와 gameObject는 상관없다고 말씀드렸는데, 그렇다고 상속이랑 아예 무관한건 또 아닙니다. 정확히 말하면 UI_Button, UI_Popup이 상속 관계이면서 UI_Popup도 타고 타고 가면 Component를 상속 받아서 그런 것이 맞습니다. GameObject는 프리팹을 Instantiate하는 순간 별도로 지정하지 않으면 프리팹이름(Clone)으로 이름이 세팅됩니다. UI_Button 프리팹을 이용해 만든 GameObject이기 때문에 이름이 그렇게 지정된 것이고, 그 상태에서 UI_Button 스크립트 Component를 붙인 상태입니다. gameObject로 접근하는 것은 원래 Component 쪽에 있는 기능인데, Component를 상속받은 애들은 당연히 그 기능을 똑같이 사용할 수 있습니다.

UI_Popup은 어느 GameObject의 Component로 붙여주지도 않았는데 SetCanvas를 호출하는게 어색하구요

-> 스크립트끼리 상속 관계가 있을 때는 각각을 별도로 생각하면 안 됩니다. UI_Button은 실질적으로 UI_Popup이기도 하고, MonoBehavior이기도 하고, Component이기도 한 것이죠. 따라서 부모가 물려준 유산은 동일하게 다 사용할 수 있습니다. gameObject는 Component가 물려준 것이니 UI_Popup에서도 사용할 수 있습니다.

그리고 UI_Button은 붙였고 UI_Popup은 붙인 적이 없다고 생각하시는데, UI_Button을 붙인 것이 곧 UI_Popup을 붙인 것도 됩니다. 애당초 상속 관계이기 때문에 둘을 분리해서 생각할 수 없습니다.

0

--님의 프로필

--

질문자

2021.04.12

흑흑 ㅠㅠ감사합니다 선생님 가려운 부분이 시원하게 긁혔습니다

0

--님의 프로필

--

질문자

2021.04.12

답변 감사합니다.

정성스럽게 써주신 답변 너무 감사합니다.. 다만 아직도 이해가 되지 않습니다.

첫 번째로 프리팹에 UI_Popup 스크립트를 실수로 붙이진 않았음을 확인했습니다.

제가 말 주변이 없어서 이번을 마지막으로 제가 궁금한 부분을 질문드리고 그래도 이해가 되지 않는다면 넘어가겠습니다.

UI_Button 클래스는 는 UI_Popup 클래스를 상속받고

UI_Popup클래스는 UI_Base를 상속받는데 

Component(gameObject 변수 소유)<----- ... <-----UI_Base <-----UI_Popup<-----UI_Button

결국 UI_Button에서 사용하는 gameObject나 UI_Popup에서 사용하는 gameObject나 UI_Base에서 사용하는 gameObject나 모두 동일한 gameObject아닌가요? 

그렇다고 어느정도 확신을 하는것이  선생님의 말씀대로 UI_Button의 gameObject와 UI_Popup의 gameObject가 상속과 관련없이 별개의 변수라면 UI_Button클래스의 Start를 시작으로 UI_Popup에 대한 SetCanvas함수 호출만 있을 뿐 UI_Button에 대한 SetCanvas함수 호출은 코드 어디에서도 찾을 수 없었습니다.. 뿐만 아니라 UI_Popup은 어느 GameObject의 Component로 붙여주지도 않았는데 SetCanvas를 호출하는게 어색하구요

ㅠㅠ너무 여러번 질문드려서 죄송합니다.. 마지막으로 가 궁금한 부분을 강사님이 캐치해주셨으면 좋겠네요

매번 감사합니다.

0

1. UI_Button에 붙은 컴포넌트는 UI_Popup.cs가 아닌 UI_Button.cs인데 어떠한 이유로 UI_Popup.cs내에서  UI_Button이라는 gameObject(base)를 갖을 수 있는지 궁금합니다. 
-> 이건 저도 알 수 없습니다.
UI_Button 프리팹에 UI_Popup 스크립트를 잘못 붙인게 아닌지 확인 바랍니다.

2. 
UI_Popup.cs의 Init에서 Managers.UI.SetCanvas(gameObject, true); 해당 코드의 gameObject는 누군가요?

-> Monobehavior를 상속받은 cs파일 또한 Component입니다.
따라서 gameObject는 당연히 UI_Popup.cs를 붙인 GameObject를 말하는겁니다.
Component는 독단적으로 존재할 수 없고, 반드시 GameObject에 기생해서 살아갑니다.
강의 코드에서는 UI를 띄울 때 어디선가 AddComponent 혹은 GetOrAddComponent 를 해서
Component를 연결 해줍니다.

UI_Button GameObject에 UI_Popup.cs이 붙은 것은 프리팹을 잘못 만든것으로 의심됩니다.

0

--님의 프로필

--

질문자

2021.04.11

오랜 시간 고민을 해도 이해가 잘 안돼서 질문 드립니다.

1.

상속 관계랑은 아무런 상관이 없고
모든 Component는 자신을 포함하고 있는 GameObject를 gameObject 로 통해 접근 가능합니다.
UI_Popup에서 gameObject 사용 가능한건 UI_Popup이 MonoBehavior를 상속 받아서 그런겁니다.
(MonoBehavior도 결국 Component를 상속 받는 구조)
gameObject에 F12를 눌러보면 아마도 Component 쪽으로 이동할꺼에요.

-> UI_Popup이 MonoBehavior를 상속받아서 gameObject를 사용할 수 있는건 이해가 가지만

UI_Button에 붙은 컴포넌트는 UI_Popup.cs가 아닌 UI_Button.cs인데 어떠한 이유로 UI_Popup.cs내에서  UI_Button이라는 gameObject(base)를 갖을 수 있는지 궁금합니다. 

답변 해 주신 "모든 Component는 자신을 포함하고 있는 GameObject를 gameObject 로 통해 접근 가능합니다." 이 말씀은 이해가 되지만 코드 어느 부분에서도 UI_Popup 클래스를 컴포넌트로 붙여주지 않았기에 더욱 의문이 생깁니다. 혹시나 이런게 가능한 이유가 상속으로 인해 가능했던건지 궁금해서 첫 질문에 올렸던겁니다.

2. 2번질문은 1번 질문과 어느정도 연관성이 있는 질문 같은데 아마 1번이 해결되면 2번도 자동으로 해결 될 것 같은 느낌이 납니다.

UI_Popup.cs의 Init에서 Managers.UI.SetCanvas(gameObject, true); 해당 코드의 gameObject는 누군가요? UI_Popup 클래스는 어느 오브젝트의 컴포넌트로 들어가지도 않았는데 SetCanvas를 한다는게 이해가 안됩니다. 오히려 해당 코드를 UI_Button.cs에서 호출하는게 맞지 않을까요?  

0

아 죄송합니다.
답변에 오타가 있었네요.

프리팹은 자기를 소유하고 있는 GameObject를 손쉽게 접근할 수 있고,
반대로 GameObject는 자신에 소유하고 있는 Component에 손쉽게 접근할 수 있는데
-> 이게 아니고

Component
은 자기를 소유하고 있는 GameObject를 손쉽게 접근할 수 있고,

반대로 GameObject는 자신이 소유하고 있는 Component에 손쉽게 접근할 수 있는데
->으로 정정합니다.

상속 관계랑은 아무런 상관이 없고
모든 Component는 자신을 포함하고 있는 GameObject를 gameObject 로 통해 접근 가능합니다.
UI_Popup에서 gameObject 사용 가능한건 UI_Popup이 MonoBehavior를 상속 받아서 그런겁니다.
(MonoBehavior도 결국 Component를 상속 받는 구조)
gameObject에 F12를 눌러보면 아마도 Component 쪽으로 이동할꺼에요.

0

--님의 프로필

--

질문자

2021.04.11

답변 감사합니다.

몇 가지 질문들 더 드리면 

2.
프리팹은 자기를 소유하고 있는 GameObject를 손쉽게 접근할 수 있고,
반대로 GameObject는 자신에 소유하고 있는 Component에 손쉽게 접근할 수 있는데
전자의 경우 gameObject를 통해 소유자에 접근이 가능합니다.
UI_Button을 Instantiate해서 만든 GameObject에
해당 cs파일 Component를 붙였으니 저렇게 뜨고 있는 겁니다.

-> UI_Button에 붙인 Component는 UI_Popup.cs가 아닌 UI_Button.cs인데 아래와 같이 UI_Popup에서 gameObject를 사용 가능한건 UI_Popup과 UI_Button이 상속관계에 있어서 그런건가요?

0

1.
프리팹은 cs 파일이 아니라서 아무런 상관이 없습니다.
동일한 class가 다수의 파일에 두 번 정의되어 있으면
컴파일 에러가 나서 애당초 통과 되지 않습니다.
따라서 구별에 대한 고민도 할 필요가 없습니다.

2.
프리팹은 자기를 소유하고 있는 GameObject를 손쉽게 접근할 수 있고,
반대로 GameObject는 자신에 소유하고 있는 Component에 손쉽게 접근할 수 있는데
전자의 경우 gameObject를 통해 소유자에 접근이 가능합니다.
UI_Button을 Instantiate해서 만든 GameObject에
해당 cs파일 Component를 붙였으니 저렇게 뜨고 있는 겁니다.

3.
세부적인 코드 하나 하나에 의미를 두지 마시기 바랍니다.
UI_Popup을 상속받는 다른 클래스에서
팝업이 닫힐 때의 행동을 재정의 하고 싶을 수도 있고 아닐 수도 있으니
그런 컨텐츠단 문제는 본인의 판단대로 작성하면 됩니다.