본문 바로가기
개발/Unity 내일배움캠프 TIL

Unity MonoBehaviour (모노비헤이비어)와 스크립트 라이프 사이클

by 석시 2023. 9. 4.



MonoBehaviour

A MonoBehaviour is a base class in C# which the unity engine provides and it allows you to attach your scripts to game objects so to create a new MonoBehaviour simply right-click, create C# script and name it what’s you like.

유니티 엔진에서 스크립트를 생성해보면, 그 스크립트가 무언가를 상속받고 있다.

그것이 MonoBehaviour이다.

public class Shape : MonoBehaviour
{
    private void Awake()
    {
        
    }

    void Start()
    {
        
    }

    void Update()
    {
        
    }
}

Mono.Net 프레임워크를 윈도우가 아닌 곳에서도 사용할 수 있는 오픈소스 개발폼이다.

유니티가 이 Mono를 기반으로 만들어졌기 때문에 이름에 Mono가 붙는 것이다.

스크립트를 사용할 때 보면 특정 오브젝트에 이 스크립트를 붙이거나, 상황에 따라 껐다 켰다 할 수 있다.

이렇게 동작(Behaviour)처럼 상황에 따라 껐다켰다 할 수 있기 때문에, MonoBehaviour라는 이름이 붙은 것이다.

스크립트의 기능 방식들은 유니티에서 미리 구현이 되어있을 것이다.

이러한 스크립트 명령들을 MonoBehaviour에서 모아놨기 때문에 모든 스크립트가 이 MonoBehaviour를 상속받아야 하는 것이다.

참고로 이렇게 미리 구현해놓고, 나중에 호출하는 함수를 콜백(callback)이라고 하고, 해당 콜백 함수들을 호출하는 것을 인보크(invoke)라 한다.


스크립트 라이프 사이클

스크립트에선 특정 상황마다 실행되는 기본 이벤트 함수들을 사용할 수 있다.

이 이벤트 함수들의 실행 시점과 반복 시점을 정리한 것이 바로 스크립트 라이프 사이클이다.

일단, 기본적인 내용은 유니티 공식 문서에 잘 정리되어 있다.

이벤트 함수의 실행 순서 - Unity 매뉴얼
Unity 스크립트를 실행하면 사전에 지정한 순서대로 여러 개의 이벤트 함수가 실행됩니다. 이 페이지에서는 이러한 이벤트 함수를 소개하고 실행 시퀀스에 어떻게 포함되는지 설명합니다.
https://docs.unity3d.com/kr/2019.4/Manual/ExecutionOrder.html

하지만 처음보면 너무 복잡해!

따라서 이번 글에서는 중요한 것만 정리를 해보려 한다.

Awake

오브젝트가 생긴 직후 실행되는 이벤트 함수.

중요 특징이 두 가지 있다.

  • 오브젝트 초기 활성화 여부와 관계 없이 호출된다!
  • 다른 모든 오브젝트가 초기화 된 후에 호출된다.

뒤에 언급될 Start보다도 빠르게 호출된다.

Manager 스크립트들은 주로 싱글톤 패턴으로 만들어주게 되는데 싱글톤 패턴으로 만들어줄 때 Awake를 사용한다.

OnEnable & OnDisable

오브젝트가 활성화/비활성화될 때마다 호출된다.

게임 플레이 중에 인스펙터 뷰를 통해 활성화해도 호출되는 것이 특이하다.

Start

Update 함수 직전에 호출되는 함수이다.

Awake와 실행 시점이 분명한 차이가 있다.

이렇게 차이를 둔 이유는, 프리팹을 두어 동적으로 인스턴스를 생성할 때 Awake에서 생성한 인스턴스를 다른 스크립트의 Awake에서 접근할 경우 순서가 달라 접근이 보장되지 않는다.

따라서 이 때는 뒤에 호출되는 것이 보장되는 Start를 이용하여 접근해주게 된다.

Update, FixedUpdate

매 단위마다 반복 호출되는 함수이다.

Update와 FixedUpdate의 차이는 예전 게시글에서 한 번 자세히 다뤘으니 참고.

[내일배움단] Unity - Update() vs FixedUpdate()
이걸 글로 따로 정리하게 된 이유는 이해가 안갔던 상황이 너무 많았기 때문이다. 바로 Time.timeScale에 관한 부분이었다.강의에서 게임을 정지하기 위해 Time.timeScale = 0; 다음과 같이 timeScale을 0으로 만들어 줬는데, 어떤 건 정지하고, 어떤 건 정지하지 않고 여전히 움직이는 이상한 상황. 문제의 장면.빗방울과 타이머는 멈췄지만, 캐릭터는 멈추지 않았다.골때리는건, 내가 따라 만든 게임은 캐릭터도 멈춰있는 것이었다. 원인을 찾아보니 차이점이 있었다.강의에서 캐릭터의 움직임을 구현할 때는 Update() 함수를 사용하였고,내가 이것을 따라만들 때는 FixedUpdate() 함수를 사용하였던 것이다. 이걸 보고 바로 알 수 있는 점은, ”Time.timeScale은 Upda..
https://seoksii.tistory.com/12

Update는 게임 로직의 주요 업데이트를 위해, FixedUpdate는 물리적인 시뮬레이션에 관련된 작업을 처리할 때 사용한다.

LastUpdate

모든 Update들의 함수들이 실행되고 나서 한 번씩 호출된다.

Update 함수에다 구현해놓은 기능의 후처리를 할 때 사용한다.

OnDestory

해당 오브젝트가 파괴 되기 직전 프레임에 호출된다.

물론 파괴되기 전에 Update 함수도 실행되야 하므로 Update - OnDestory 순으로 호출이 된다.

자원 정리 및 해제 작업을 수행할 때 사용한다.


Serialize

MonoBehaviour의 기능으로 변수들을 Serialize 할 수 있다.

스크립트의 변수를 인스펙터뷰에서 보고 싶다면, 제일 먼저 생각할 수 있는 것은 변수 앞에 public 한정자를 달아 주는 것이다.

하지만 해당 방식은 살짝 위험한데, public 변수들은 인스펙터뷰에만 노출되는 것이 아니라, 다른 스크립트들에게도 노출되기 때문이다.

따라서 MonoBehaviour에서 SerializeField라는 키워드를 제공해준다.

[SerializeField]를 변수 앞에 붙이게 되면 인스펙터뷰에서는 보거나 조작하는 것이 가능하지만, 다른 스크립트에서 참조할 수 없게 되어 안전해진다.

[SerializedField]private float _speed;

반대로, 다른 스크립트에서는 접근 가능하게 (Accessible) 하게 만들고 싶지만, 인스펙터뷰에는 보이지 않도록 하고 싶은 경우도 있을 것이다.

이 경우는 [HideInInspector]라는 키워드를 쓸 수 있다.

[HideInInspector]public Vector3 Direction;


Monobehaviour 주의점

  1. 스크립트 자체만으로는 사용할 수 없다.

반드시 Component로 존재해야 작동한다.

싱글톤 패턴으로 사용하는 Manager류 스크립트들도 마찬가지다.

반드시 빈 오브젝트라도 선언해주고 스크립트를 붙여주자.

  1. 아무 내용도 없는 이벤트 콜백은 지워주자.

내용이 없더라도 무조건 호출된다!

이 때 함수 호출을 위한 오버헤드가 발생해 성능에 악영향을 끼친다.

따라서 쓰지 않는 MonoBehaviour 함수들은 꼭 지워주자.

  1. new로 동적할당이 되지 않는다.

AddComponent<>()라는 따로 구현된 함수를 사용해야 한다.


Uploaded by N2T