Game/Unity

[유니티] 유니티 엔진 원리

nowkoes 2023. 2. 9. 13:32

<본 글은 레트로의 유니티 게임 프로그래밍 에센스(개정판)을 참고로 하여 작성하였습니다>


상속

 게임 엔진은 이미 완성된 기반 코드를 제공한다. 지금까지 포스팅해온 게시글을 움직이는 것(translate)과 충돌하는 것(OnTrigger)과 같이 이미 작성된 코드를 재사용하여 게임을 만들었다. 이러한 '재사용'과 관련이 깊은 키워드는 바로 상속이다. 하지만 유니티 엔진에서는 이러한 상속을 유니티를 동작시키는 데 있어 핵심이라고 부르진 않는다. 왜 그럴까? 바로 상속의 한계 때문이다.

 

 게임을 만들 때 상속의 한계는 명확하다. 상속에 의존하다보면 오히려 코드의 재사용이 힘들어지고, 추후에 자식 클래스와 부모 클래스의 기능이 충돌하는 등 더욱 번거로워지기 때문이다. 예를 들어보자. RPG 게임에서 플레이어와 NPC, Monster를 상속을 이용해 만든다고 가정해보면, 이들의 기반인 Human 클래스를 먼저 설계를 해야한다.

 

Human 클래스에 정의할 틀과 슈도 코드

 

 이렇게 작성하고 나서, Human 클래스를 상속하는 Player, NPC, Monster 클래스를 만들어보자.

 

Human을 상속하는 세 개의 클래스와 그 코드

 

  Player 클래스에서는 Human 클래스를 그대로 받아와 몇 가지만 추가해주면 되어 별 문제가 없다. 하지만 NPC와 Monster클래스를 보면 Animation을 다시 작업해줘야 하거나, 기존의 기능을 제거해야하는 등 몇 가지 절차가 새로 생긴다. 즉, 재사용성을 위한 상속의 의미가 퇴색되어 버린다. 따라서 유니티에서는 이러한 문제를 해결하고자 컴포넌트(Component) 패턴을 사용한다.

 

컴포넌트 패턴

 컴포넌트 패턴, 혹은 컴포지션(Composition) 패턴은 미리 만들어 놓은 부품인 컴포넌트를 빈 껍데기인 게임 오브젝트에 추가하여 새로운 오브젝트를 만드는 방식이다. 앞서 언급한 Player, NPC, Monster를 컴포넌트를 이용해 만드는 것을 가시화하면 다음과 같다.

 

 

 먼저 미리 컴포넌트를 만든다(Component). Player와 NPC, Moster라는 오브젝트를 만든 후에 필요한 기능들을 오브젝트에 넣어 게임 오븢벡트에 실질적인 기능을 부여하면 끝이다. 이러한 방식은 다음과 같은 장점들이 존재한다.

  • 유연한 재사용 가능
  • 독립성

 즉, 원하는 기능만 골라서 사용할 수 있어 불필요한 코드 재사용을 줄일 수 있고, 독립성 때문에 컴포넌트가 제거되더라도 게임 오브젝트 자체는 전혀 망가지지 않는다. 그런데, 유연한 재사용이 가능한 이유는 알겠는데, 왜 독립적일까? 이는 유니티가 컴포넌트 구조에서 브로드캐스팅(Broadcasting) 방식을 채택하기 때문이다.

 

브로드캐스팅

 

 유니티의 모든 컴포넌트는 MonoVehaviour이라는 컴포넌트에 필요한 기본 기능을 제공하는 클래스를 상속받고 있다. 따라서 컴포넌트는 유니티의 제어를 받게 되어서 유니티가 보내는 메시지를 받을 수 있게 된다. 이러한 메시지는 게임 오브젝트에 어떤 컴포넌트가 추가되었을 때, 그 기능을 실행시키는데 사용된다. 예를 들어 RigidBody라는 컴포넌트를 찾으려면 유니티 게임 세상 전역에 RigidBody라는 메시지를 뿌리고, 메시지를 받은 오브젝트가 명시된 기능을 갖고 있다면 해당 기능을 실행하는 방식이다. 이런 방식으로 메시지를 무차별적으로 여러 오브젝트에 동시에 뿌리는 것브로드캐스팅이라고 한다. 따라서 특정 오브젝트를 직접 가리키지 않고 원하는 기능을 수행하게 되어 독립성을 갖게 된다고 할 수 있다. 이는 추후에 다룰 이벤트 메서드가 동작하는 원리가 된다.


요약

컴포넌트(Component) 패턴
1. 정의: 부품인 컴포넌트를 오브젝트에 조립하여 완성된 오브젝트를 구현하는 것
2. 특징
 a. 유연한 재사용성
 b. 독립성
3. 브로드캐스팅(Broadcasting)
- 메시지를 무차별적으로 여러 오브젝트에 동시에 뿌리는 방식

 

반응형