Game Object
게임 오브젝트란 레벨에 배치할 수 있는 오브젝트를 말합니다. 게임 오브젝트는 이동, 회전, 스케일과 같은 트랜스폼을 지원하는 범용 클래스입니다. 한마디로 화면상에 존재하는 UI, 몬스터, 플레이어 등등 씬을 구성하는 단위라고 생각하면 됩니다.
그리고 게임 오브젝트 안에는 여러가지 다른 부속품(component)들이 존재합니다.
예를들어 Transform 은 크기 이동 각도 같은 작업을 담당하고 SpriteRenderer는 화면상에 그림을 그려주는 역할을 합니다. AudioSource는 소리를 재생시켜주는 역할을 하구요.
이렇게 여러개의 씬과 그 씬안에 존재하는 오브젝트들을 배치하여 게임을 만들게
됩니다.
상속 구조
게임 오브젝트를 설계할때 가장 보편적인 구조는 상속을 이용한 계층 구조입니다.
가장 보편적으로 사용 되었던 오브젝트 계층 구조 설계에 대해 이야기를 해보려 합니다.
계층 구조 설계는 말 그대로 오브젝트가 하는 기능을 중심으로 계층을 만들어 설계를 하는 것입니다.
Player, Monster, Prop의 공통된 부분은 GameObject에서
처리를 하고 나머지 부분은 각각의 오브젝트 에서 구현하여 실행하면 됩니다.
여기에 Player와 Monster는 움직이는 계층구조를 하나 추가해보겠습니다.
움직임 관련된 처리는 이 MovableObject에서 하면 되고 그 외에 Player, Monster에 특화된 다른 처리들을 각각 하면 되겠죠
여기에 이제 Trigger 라는 오브젝트를 추가하려고 합니다.
그런데 Trigger은 화면에 그려지지 않는 오브젝트입니다. Player, Monster, Prop과는 다른 속성이 생긴 것이죠. 그렇다면 역시 그려지는 것을 처리하는 계층을 하나 더 추가하는 것입니다.
이제
그려지는 부분은 RenderableObject에서 처리를 하면 되니 중복 코드도 없고 아주 깔끔하게 해결이 되었습니다.
이런 식으로 공통된 부분들을 묶어서 중간계층을 추가하여 설계해 나가는 방식을
게임 오브젝트의 계층 구조 설계 라고 합니다.
하지만 게임이 점점 복잡해짐에 따라 게임 오브젝트의 타입도 다양해지고 하는 일도 많아져서,
계층 구조 설계를 사용하여 게임 오브젝트를 만드는데 어려움이 생기기 시작하였습니다.
예를 들어 위 상황에서 Camera를 추가한다고 가정해봅시다.
카메라는 화면에 그려지는 오브젝트가 아니니까 이렇게 추가하면 되는 것일까요?
카메라는 화면에 그려지진 않지만 움직일 수는 있습니다.
그럼 움직일 수 있는 오브젝트니까 이렇게 추가하면 되는 것일까요?
안타깝게도 카메라는 화면에 그려지는 오브젝트가 아닙니다!!
그려지진 않지만 움직일 수는 있는 오브젝트가 생기니 약간 골치가 아파졌습니다.
어쩔 수 없이 Prop과 Trigger에게는 미안하지만 GameObject에서
움직임 처리를 하고 Prop과
Trigger에서는 사용하지 않기로 해봅시다.
이렇게 만들고 보니 클래스 계층 구조만 보면 더 깔끔해진 것 같습니다.
클래스 계층 구조는 더 깔끔해졌지만 GameObject의 비중은 점점 더 커져만 갑니다.
오브젝트의 타입이 늘어나면 늘어날수록 기능이 추가될수록 점점 더 설계는 복잡해지고 상위
계층은 비대해집니다.
그래서 이런 문제를 해결하기 위해 컴포넌트 기반 설계가 부각되기 시작하였습니다.
컴포넌트 구조
게임 오브젝트의 컴포넌트 구조는 상속구조의 문제점을 보완하고자 제안된 설계 방법입니다.
컴포넌트 기반 설계는 게임 오브젝트가 해야 할 긴으들을 각각 별도의 객체에 분할하여
게임 오브젝트의 클래스 기능이 비대화 되는 문제점을 해결하는 설계입니다.
컴포넌트 기반 설계에서 게임 오브젝트는 각 타입에 따라 사용되는 컴포넌트들로 구성됩니다.
오브젝트마다 필요한 기능이 있다면 그 기능을 하나의 컴포넌트로 만들고 컴포넌트들을 추가하여 하나의 게임 오브젝트를 구성합니다. 게임 오브젝트는 단지 여러개의 컴포넌트들을 관리 할뿐이죠.
유니티 컴포넌트 구조
언리얼 컴포넌트 구조
이미 유니티 엔진과 언리얼엔진에서는 이러한 컴포넌트 기반 구조를 채택하여 사용하고 있습니다.
이제 우리 프로젝트도 이 기반으로 게임 오브젝트를 설계하여 보겠습니다.
오브젝트는 여러개의 컴포넌트를 가지고 있고 각각의 컴포넌트들을 순회하면서
Render와 Update 함수만을 호출해주고 있습니다. 그러면 이 컴포넌트들을 상속받은 Animation , Collider 컴포넌트들을 가상함수를 이용해서 구현이 된부분들이 자식객체들로 알아서 호출이
될것 입니다.