[Unity] MonoBehaviour 총정리 및 생명주기(Lifecycle)
본문 바로가기
프로그래밍/Unity

[Unity] MonoBehaviour 총정리 및 생명주기(Lifecycle)

by [아마군] 2019. 9. 17.
반응형

1. 모노 (Mono)

.Net은 마이크로 소프트(MicroSoft)에서 C언어에 자바의 장점을 수용하여 개발한 MS Windows 프로그램 개발 및 실행 환경이자 언어이다.

 

네트워크와 UI 등의 많은 작업을 캡슐화 하여 코딩의 효율성을 극대화 한 .Net 의 강력한 기능을 사용하기 위해서는 .Net 프레임워크가 설치 된 윈도우 환경이 있어야 했다.

 

이에 윈도우가 아닌 다른 플랫폼에서 .Net 프레임워크를 사용하기 위해 개발된 것이 얼마 전 MS에서 인수한 자마린(Xamarin) 사의 Mono 이다.

 

Mono 는 .Net 프레임워크(framework) 의 오픈소스 개발 플랫폼으로서 크로스플랫폼(Cross-platform) 어플리케이션의 개발을 지원하며 C#과 CLI (Common Language Infrastructure) 에 기반을 두고 있다.

 

Mono 를 활용한 대표적인 크로스플랫폼 개발 도구가 유니티와 자마린 이다.

 

현재 유니티에서 사용하는 Mono 의 .Net 컴파일러에서 지원하는 .Net 버전은 4.x 로 C# 7까지 사용할 수 있다고 한다.

 


2. 스크립트 언어 (Script Langauge)

하나 이상의 어플리케이션 에서 스크립트(script)를 지원하는 프로그래밍의 부분 집합(subset)이다.

 

스크립트는 흔히 어플리케이션의 코어 코드와는 별개의 언어로서 최종 사요아에 의해 작성되거나 최소한으로 수정되는 프로그램이다.

 

스크립트는 대개 소스코드나 바이트코드로 부터 해석되며 이는 어플리케이션이 기계어나 중간언어로 컴파일되는 것과 차별화 된다.

 

그런면에서 스크립트 언어인지 아닌지를 결정하는 것은 언어 그 자체가 아니라 그 언어가 사용되는 환경이다.

 


3. Unity 의 Behaviour Script

유니티에서 하나의 스크립트는 그 자체로 하나의 클래스(Class)를 뜻한다.

 

클래스란 속성(Properties), 메서드(Method) 들을 하나의 객체로 묶은 데이터 타입이다.

 

유니티에서 하나의 스크립트는 각각 속성(Properties), 변수(Variables), 명령(Instructions) 또는 기능(Functions)을 가지며 사용자는 원하는 순간에 해당 스크립트를 호출 할 수 있다.

 

모든 스크립트는 또한 Behaviour Component 이다.

 

Behaviour 는 활성화(Enable), 비활성화(Disable) 할 수 있는 Component 이다.

 

즉, Behaviour는 껐다켰다 할 수 있는 동작(behaviour) 이며, 이는 캐릭터의 동작이 될 수도 있고, 환경이 될 수도 있고, 게임 내 흐름을 제어하는 프로그램 자체가 될 수도 있다.

 

* Component 란? GameObject 에 부착되는(Attached) 모든 것들이 상속받는 기반 클래스.

 


4. MonoBehaviour

MonoBehaviour 는 Unity 의 모든 스크립트가 상속받는 클래스이다.

 

사용자가 Unity 엔진의 작동 방식을 이해하지 못하더라도 코드를 작성할 수 있도록 미리 만들어 둔(built-in) Behaviour 클래스 이자 스크립트 명령(scripting instruction) 들의 집합이다.

 

덕분에 모든 스크립트는 유니티 엔진에 의해 호출(invoke) 되는 콜백(callback) 함수들을 이용할 수 있게 된다.

 

이 콜백 함수들은 Reset, Awake, Start, Update, OnGUI, OnDestroy 등 유니티를 사용하면서 수없이 사용하게 된다.

 


5. MonoBehaviour 의 생명주기(Lifecycle)

 

유니티의 공식 매뉴얼을 보면 위와 같이 MonoBehaviour 의 수많은 콜백함수 종류와 각각이 호출 되는 시점을 알 수 있다.

 

이 중 개발 과정에서 실제 자주 이용하게 되는 콜백들의 라이프사이클을 살펴보자.

 

Reset : 유니티 에디터에서 오브젝트 생성 후 인스펙터 뷰에서 리셋을 눌러줄 때 실행된다.

          객체의 속성을 초기 값으로 설정해 줄 때 사용한다.

 

Awake : 프리팹이 인스턴스화 한 직후, 스크립트가 호출되자마자 오브젝트 활성화 여부와 상관없이 실행 된다.

           모든 오브젝트가 초기화 된 후 호출되기 때문에 GameObject.Find 같은 명령문을 안전하게 사용할 수 있다.                 Awake 함수는 언제나 Start 함수 전에 호출되는 점에 주의. (StartCoroutine 을 사용할 수 없다.)

 

OnEnable : 다른 초기화 함수와 달리 하나의 라이프 사이클 내에서 여러번 호출 될 수 있다.

                인스펙터뷰에서 체크 및 스크립트 내에서 SetActive 함수로 게임 오브젝트를 활성화 할 때마다 호출 된다.

 

Start : Update 함수가 호출되기 전에 한번만 호출된다.

         다른 스크립트의 모든 Awake가 모두 실행된 이후에 실행되며 Awake와 달리 오브젝트가 활성화 되어 있어야 호출 된다.

         Awake 이후 호출되므로 예를들어 A 객체의 Awake 함수에서 동적 생성한 멤버를 B객체의 Awake 함수에서 접근할 경우 오브젝트 들의 Awake 함수 호출 순서는 임의로 정할 수 없으므로 B객체의 Awake 가 먼저 호출 되어 NullReferenceExecption 을 발생 시킬 수 있다.

         이럴 경우 동적 생성은 Awake 에서 하고 동적 생성되는 멤버에 접근하는 초기화 코드는 항상 Awake 이후로 보장되는 Start 에 넣는 것이 좋다. 

 

FixedUpdate프레임과 상관없이 무조건 시간 기준(default 0.02초. 변경 가능)으로 호출 되는 Update 콜백이기 때문에 주로 물리 엔진을 사용하는 경우 일정 시간 간격으로 힘을 가하거나 체크할 때 사용한다.

                   프레임 속도가 기준 시간 속도보다 오래 걸릴 정도로 느려질 경우 한 프레임에서 여러번 호출 될 수 있다.

 

Update : 매 프레임마다 호출되는 가장 일반적인 Update 함수.

             오브젝트가 활성화 되어 있어야 호출 되며 프레임 단위이기에 호출 시간 간격은 프레임에 따라 변한다.

 

LateUpdate : 모든 Update 계열 콜백들이 실행되고 나서 호출된다.

                  Update 함수에서 캐릭터를 이동 시킨 후 LastUpdate에서 캐릭터의 좌표를 추적해 카메라의 좌표를 이동시키는 등의 경우에 사용한다.

 

OnDisable : 게임 오브젝트 또는 스크립트가 비 활성화 되었을 때 호출된다. (StartCoroutine 사용 불가)

 

OnDestroy : 해당 오브젝트가 파괴 되기 전 프레임의 Update 함수 실행 후 호출 된다.

                 일반적으로 라이프 사이클 내에서 사용한 자원들을 돌려 놓는 작업을 이곳에서 하게 된다.

 

OnApplicationQuit :  앱이 종료 되기 직전에 모든 오브젝트에서 호출된다.

                             에디터에서는 플레이 모드 중지할 때 호출 된다.

 


6. MonoBehaviour 의 특징

MonoBehaviour 를 상속받은 스크립트 파일은 그 자체로 사용할 수 없다.

 

GameObject 에 Component 형태로 등록되어 있어야 한다.

 

즉, 게임 내에서 사용할 GameManager.cs 라는 스크립트 파일을 만들었다면 해당 클래스를 적용할 빈 GameObject를

 

Unity의 Hierarchy 에서 추가한 후 Inspector 창에 이 스크립트 파일을 등록한다.

 

그리고 코드에서 해당 GameManager 클래스를 가져오려면 위에서 추가한 GameObject 객체에 GetComponent<GameManager>(); 형태로 가져와야 한다는 뜻이다.


또한 가장 중요한 특징 중 하나는 MonoBehaviour 를 상속받은 클래스는 new 로 동적 할당할 수 없다.

 

이 경우,

 

1. GamObject.Instantiate 함수를 통해 해당 스크립트가 Component 로 추가된 오브젝트의 인스턴스를 생성

2. 기존 생성된 GameObject 객체에 AddComponent<GameManager>();

 

하여 사용할 수 있다.


MonoBehaviour 의 다양한 콜백 함수는 필요할 경우 오버라이딩 해서 사용하면 된다.

 

하지만 오버라이딩 해놓고 해당 함수 안에서 아무것도 하지 않고 비워두면 어떻게 될까?

 

컴파일 과정에서 이런 경우 함수 호출을 제거해 주면 좋으련만 아쉽게도 내용이 있던 없던 무조건 호출을 진행 한다.

 

Awake 나 Start 같은 한번만 호출 되는 경우는 상대적으로 영향이 적겠지만 FixedUpdate 같은 경우 0.02초 마다 오브젝트 별로 각각 호출을 하게 되므로 퍼포먼스에 상당한 영향을 끼칠수 있다.

 

쓰지 않는 MonoBehaviour 함수는 꼭 삭제해 주자.

반응형

댓글