• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

static에 관해서 질문이 있습니다.

21.06.22 19:01 작성 조회수 299

0

강의를 보면서 C#에 대한 이해를 최대한 하면서 공부를 하고있는데요. 마이크로소프트 공식 문서와 기타 책들도 참고하면서 하고 있는데 static 한정자가 유니티에서 쓰일 때 좀 다른점이 있는 것 같아서 질문드립니다. 이것저것 테스트해보았는데도 의문점이 풀리지 않는 부분들이 있어서요..

첫번째 질문은 -  Part1,2에서 진행했던 콘솔앱같은경우, 다른 클래스에서 static한정자를 사용해서 필드변수등을 만들었을 때, 그냥 program의 Main에서 타클래스에서 선언한 static 필드변수를 new 키워드도 사용하지 않고 그대로 가져다가 사용할 수 있었습니다. 

실제로 결과는 0, 100이 찍힌걸로 보아 new Class1을 하지 않았음에도 분명 어딘가에 메모리상에 Class1 클래스가 만들어져서 존재하고 myValue라는 값도 존재한다는 의미로 받아들였는데 일단 이부분의 이해가 맞는지 궁금합니다.

두번째로 - 위와 같은 방법으로 유니티에서도 실험을 해보았는데,  

일단 디버그 안에서 TestManager.Instance로 바로 접근이 가능했지만, a의 값을 가져오는거에는 실패를 한게 어째서인지 모르겠고

그다음에 위에 Instance.a가 널래퍼런스 오류라서 TestManager를 새로 만든 뒤에 tm에서 a를 가져왔지만 그값이 100이 아닌 0인 이유도 모르겠습니다. (왜 TestManager의 Start안에서 초기화하는 부분이 실행이 안됐는지)

a 자체를 static으로 하지 않아서 그런가 싶어서 int a에도 static을 붙여보았는데 그렇게하면 TestManaget.Instance.a가 아닌 TestManager.a로 바로 접근이 가능했습니다만, 싱글톤 패턴을 사용하는 방법에선 Instance를 사용해서 접근하는게 목적인 것 같아서 의미가 없는게 아닌가요?

세번째로 강의를 보면 Init()함수에서 Instance가 null이라면 찾아서 넣어주는 작업을 하는데, 애초에 new키워드를 쓰지 않고도 이미 Managers.Instance에 접근이 가능하다는 것 자체가 이미 Managers라는 어딘가에 존재하는 클래스를 가져왔다고 생각되는데, 왜 Instance = 자기자신으로 바로 가져오지 못하고 null상태로 존재할 수 있는지가 궁금합니다.

메모리상에 존재하지 않는다면 애초에 Managers.Instance에 접근자체를 할 수 없던가, 그렇지않다면 Instance를 찾은시점에 Instance타입자체가 Managers이므로 자기자신을 선택할 수 있어야하는게 아닌가요?

마지막으로 static키워드 자체가 유일성을 보장받는다는게 핵심이고, 그것덕분에 그냥 Managers.~~~방식으로 접근할 수 있다는부분에서, 결국 Managers 스크립트가 컴포넌트의 형태로 씬 어딘가에 존재해야만 가져다가 쓸 수 있다면 반대로 Managers 스크립트가 붙은 오브젝트가 하나가 아닌 여러개 존재할 때, Managers안의 Instance의 유일성은 보장받지 않는게 아닌가요? 만약 Managers를 가지고있는 복수의 게임오브젝트가 존재할 경우, Managers.Instance로 뭔가에 접근한다면 어떤 게임오브젝트의 Managers에 접근하는건가요? 그리고 Managers 자체가 복수로 존재하는거 자체가 가능한게 잘못 된 것 같은데 정작 Managers를 가진 게임오브젝트를 복제하고 실행해봐도 아무 문제가 없어보여서 질문드립니다.

혼자 공부하느라 최대한 이것저것 다 찾아보고 하면서 공부하고 있는데 static과 싱글톤 개념이 약간 이해가 어려워서 염치불구하고 질문드립니다...ㅜㅜ

답변 1

답변을 작성해보세요.

0

실제로 결과는 0, 100이 찍힌걸로 보아 new Class1을 하지 않았음에도 분명 어딘가에 메모리상에 Class1 클래스가 만들어져서 존재하고 myValue라는 값도 존재한다는 의미로 받아들였는데 일단 이부분의 이해가 맞는지 궁금합니다.

-> static 변수는 특정 class랑 아무 상관이 없습니다. 그냥 코드상으로 해당 class 안에 정의되어 있을 뿐, Class1이 만들어져 존재하는 것은 아닙니다.

일단 디버그 안에서 TestManager.Instance로 바로 접근이 가능했지만, a의 값을 가져오는거에는 실패를 한게 어째서인지 모르겠고

-> 정답은, TestManager 타입이 참조값이기 때문에, new로 생성하지 않는 이상 일반 정수처럼 막 쓸 수 없기 때문입니다. 참조값은 사실상 [주소를 담는 변수]입니다. C++로 치면 포인터로 이해하시면 되고요.

그다음에 위에 Instance.a가 널래퍼런스 오류라서 TestManager를 새로 만든 뒤에 tm에서 a를 가져왔지만 그값이 100이 아닌 0인 이유도 모르겠습니다. (왜 TestManager의 Start안에서 초기화하는 부분이 실행이 안됐는지)

-> Start가 호출 안 되서 그렇습니다. 객체를 만든다고 바로 Start가 호출되는 것은 아니고, Scene에 GameObject를 만들어서 거기다가 해당 Component를 붙여줘야 비로소 Start가 호출됩니다. 그래서 그냥 new TestManager를 한다고 Start가 호출되는 것은 아닙니다.

세번째로 강의를 보면 Init()함수에서 Instance가 null이라면 찾아서 넣어주는 작업을 하는데, 애초에 new키워드를 쓰지 않고도 이미 Managers.Instance에 접근이 가능하다는 것 자체가 이미 Managers라는 어딘가에 존재하는 클래스를 가져왔다고 생각되는데, 왜 Instance = 자기자신으로 바로 가져오지 못하고 null상태로 존재할 수 있는지가 궁금합니다.

-> 그렇지 않습니다. Managers.Instance가 접근 가능한 것은 맞지만 어디까지 참조값이기 때문에, new 등으로 생성해주지 않는 이상 기본 값은 null입니다. 그리고 유니티에서 MonoBehavior 상속받는 클래스는 사실 new로 만들어줘서도 안 되고, AddComponent 형태로 GameObject에 반드시 붙여줘야 합니다.

마지막으로 static키워드 자체가 유일성을 보장받는다는게 핵심이고, 그것덕분에 그냥 Managers.~~~방식으로 접근할 수 있다는부분에서, 결국 Managers 스크립트가 컴포넌트의 형태로 씬 어딘가에 존재해야만 가져다가 쓸 수 있다면 반대로 Managers 스크립트가 붙은 오브젝트가 하나가 아닌 여러개 존재할 때, Managers안의 Instance의 유일성은 보장받지 않는게 아닌가요? 만약 Managers를 가지고있는 복수의 게임오브젝트가 존재할 경우, Managers.Instance로 뭔가에 접근한다면 어떤 게임오브젝트의

-> static이 유일한 것은 맞고 Instance가 유일한 것도 맞지만, 실제로 Instance가 가리키는 애는 유일하며 우리가 직접 코드에서 만든 애를 가리키기 때문에, 직접 Managers를 붙은 오브젝트를 툴상에서 만들어도 아무런 영향을 받지 않습니다.