우선 프로그래밍적 관점에서 게임이란 간단히 정의하자면
가상의 세계 속에서 물체가 상호작용하는 것을 말한다.
상호작용이 사용자와의 상호작용이거나 물체와 물체 간의 상호작용일 수도 있다.
Unity에 있어서 물체를 GameObject로 정의하고 GameObject는 유니티 내의 모든 요소를 표현하는 기본적인 개체 단위를 말한다. 눈에 보이든 보이지 않든 모든 Scene 위의 것은 GameObject로 표현된다.
GameObject는 게임의 구성요소를 가지고 있는 컨테이너 역할을 하고 Gameworld에서 위치를 가지고 다른 GameObject와 상호작용을 하면서 게임을 구성한다.
GameObject는 다양한 컴포넌트를 가지고 있고 컴포넌트를 이용해 게임오브젝트의 상호작용을 제어할 수 있다.
Unity에서 Script로 GameObject를 가져오는 방법을 간단히 소개할까 한다.
방법 1 - Public 변수, 혹은 SerializeField를 이용해 인스펙터창에 넣어주기
[SerializeField] private DTScrollView _scrollRect;
[SerializeField] private UIStoryImagePanel _imagePanel;
[SerializeField] private UIStoryButtonPanel _buttonsPanel;
장점
- 추후 설명할 방법에 비해 런타임중 자원 비용이 감소된다.
- 하이어라키상의 구조가 자주 변경되는 경우 유리하다.
왜냐하면 하이어라키창을 수정하더라도 새로 정의하거나 코드를 수정할 필요가 없기 때문이다.- 주로 코드가 포함되어 빌드된 앱의 경우에는 마켓 정책으로 인해 검수 후 릴리즈 되는 경우가 많다. 번들의 경우는 사용자가 앱 내에서 다운로드하는 형식이라 마켓검수가 없더라도 언제든지 수정이 가능한데 이때 편하게 구조를 변경할 수 있어서 코드가 프리팹보다 먼저 들어가야 할 때 유리하다.
- 어떤 부분이 연결이 되지 않았는지 한눈에 파악이 쉽다.
단점
- Unity 내부에서 변경하는 게 아니라 외부에서 변경 시 meta 파일이 깨지거나 손상될 수 있다.
- 만약 meta를 잘못 관리하거나 연결된 오브젝트를 삭제하여 missing 이 날 경우 번들 관리 시스템에서는 0 즉 아예 넣지 않은 상태와 missing을 구분하지 못하기 때문에 관리에 실패하여 missing의 경우 최악의 상황에서는 앱크래시라는 끔찍한 결과를 가져온다.
- 앱크래시란 앱이 강제로 종료되는 경험을 말한다. 만약 최고 기록을 경신하고 있거나 주 1회밖에 참여하지 못하는 중요한 레이드를 앱크래시로 기회를 날린다? 게임 사용자 경험에 정말 최악인 일이다.
- 앱크래시는 사용자 경험에 최악이며 일어나면 안 되는 일 중 하나이므로 꽤 리스크가 큰 편이다. 이 치명적 단점 때문에 되도록이면 사용을 하지 않는 경우가 많다.
- 런타임 중에 불러올 수가 없다. 즉 동적으로 생성되는 오브젝트의 경우에는 해당 방법을 이용할 수 없다.
단점들의 해결방안
- 모든 인스펙터창의 변경은 유니티 에디터에서 변경해 준다.
- 번들에 있는 컴포넌트가 비어있는 경우중 missing 난 것을 골라주는 건 내가 아는 한 유니티 내부에는 없다.
따라서 커스텀해서 null 이거나 missing을 골라주는 툴을 제작하거나 missing 이 나지 않도록 관리나 확인을 잘하는 방법밖에 없다. - 런타임 중 가져와야 하는 경우를 되도록 만들지 말자. 만약 필요하다면 transform.Find ( 방법 2를 이용한다)
방법 2 - transform.Find 함수를 이용해 찾아 넣어주기
Transform objectC = transform.Find("A/B/C");
Transform objectA = transform.Find("A");
장점
- Unity 내부가 아닌 외부 ( 개발도구 등)에서 변경되어 손상되어도 문제가 되지 않는다.
- meta 관리나 missing과 같은 치명적인 부분에 있어서는 자유롭다.
- 런타임 중에 불러올 수 있다.
단점
- 최적화에 치명적이다.
- Find로 찾는 방법은 결국 transform 하위에 있는 오브젝트들의 string을 배열형태로 검색하는 방식 즉 string 비교가 들어가는데 string 비교 시에는 반드시 GC 가 발생하므로 자주 사용할 경우 프레임드롭을 유발할 수 있다.
- 하이어라키상의 구조가 변경될 경우 코드가 수정되어야 한다
- 자주 변경되는 경우 프리팹 즉 번들로만 해결이 가능한데 하위에 있는 object 가 코드에서 쓰여서 수정해야 하는 경우는 무조건 코드를 수정해주어야 하기 때문에 자주 변경되는 경우 번거로운 면이 있다.
- 어떤 부분이 연결되지 않았는지 코드와 프리팹을 일일이 비교하거나 런타임도중 디버깅을 통해서만 알아낼 수 있다.
단점들의 해결 방안
- 자주 사용하지 않는다. Update 같이 프레임마다 불리는 함수들에서는 거의 사용을 금기시하고 있을 정도로 사용하지 않는다. Awake , Start 같은 해당 오브젝트가 생성될 때 한 번만 호출되는 이벤트 함수에서만 사용하는 것을 대부분의 책에서 권장하고 있다.
- 하이어라키상의 구조가 변경될 때 프리팹 작업자가 반드시 해당 컴포넌트 프로그래머에게 노티를 준다.
- 꼼꼼하게 코드와 프리팹을 비교하여 null이 되지 않도록 확인한다.
이 두 가지 방안이 내가 알고 있는 Unity에서 GameObject를 가져오는 거의 유일한 방법이다.
두 가지 방법 중에 현재 구현 중인 프로젝트에 알맞은 방식을 적절히 사용하는 게 좋다.
반응형
'엔진공부 > 유니티 공부' 카테고리의 다른 글
Unity Shader 사용 방법 (0) | 2024.02.04 |
---|---|
신입 개발자가 유니티 공부하고 포트폴리오 준비한 방법 (게임 개발 취업 준비) (1) | 2023.05.31 |
Addressable PatchSystem 이란 (0) | 2023.04.17 |