1. 유니티 생명 주기란?
컴포넌트들과의 상호작용 그리고 사용자 입력에 대한 반응들을 통해 오브젝트를 제어 할 수 있다고 했습니다. 이러한 상호작용과 반응은 순차적이고 구조화된 방식으로 이루어집니다. 이를 가능하게 하는 것이 바로 유니티의 생명 주기(Life-cycle) 입니다. 이는 객체가 생성되고 활성화되며, 업데이트되고, 종료되는 과정을 의미합니다. 이 생명주기에는 여러 이벤트 메서드가 존재하며, 이를 통해 게임 오브젝트의 동작을 제어할 수 있습니다.
아래 이미지는 유니티의 생명 주기의 흐름도를 보여줍니다. 생명 주기는 주요 이벤트 메서드들로 구성되며, 각 메서드는 필요한 각 단계에서 호출됩니다.
1.1 Awake()
Awake()는 게임 오브젝트가 비활성 상태에서도 호출되며, 씬(Scene)이 로드될 때마다 모든 오브젝트에 대해 한 번만 호출됩니다. 또한, 해당 게임 오브젝트의 모든 스크립트에 있는 Awake() 메서드가 실행되기 전에는 다른 게임 오브젝트나 컴포넌트에 의존하지 않는 초기화 작업을 수행하는 것이 좋습니다.
Awake() 메서드를 사용하여 수행할 수 있는 일은 다음과 같습니다.
- 게임 오브젝트의 변수 초기화
- 컴포넌트 가져오기 및 초기화
- 게임 매니저나 싱글톤과 같은 다른 게임 오브젝트에 대한 참조 설정
Awake()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있지 않기 때문에 사용자가 작성해야합니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void Awake()
{
// Some initialization code here
}
1.2 OnEnable()
OnEnable() 메서드는 게임 오브젝트가 비활성화되거나 스크립트가 비활성화된 후 다시 활성화될 때마다 호출되기 때문에, 재활성화시 필요한 작업을 수행하는데 적합합니다. 유니티에서 이벤트 등록, 이벤트 리스너 설정, Coroutine 시작 등의 작업에 많이 사용됩니다. (이벤트 등록, 이벤트 리스너, Coroutine은 추후 글에서 설명합니다.)
OnEnable()은 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있지 않기 때문에 사용자가 작성해야합니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void OnEnable()
{
// Some enabling code here
}
게임 오브젝트의 활성화 상태는 인스펙터 패널에서 체크 박스를 통해 제어할 수 있으며, 스크립트에서는 gameObject.SetActive(true) 또는 gameObject.SetActive(false)와 같은 메서드를 사용하여 제어할 수 있습니다.
1.3 Start()
Start()는 게임 오브젝트나 컴포넌트를 초기화하는데 사용됩니다. 그러나 Awake()와 달리 Start()는 게임 오브젝트가 활성화되는 동안 한 번만 호출되므로, Awake()에서 초기화된 다른 스크립트나 컴포넌트에 의존하는 초기화 작업을 수행하는 데 사용됩니다.
또한, Start()는 게임 오브젝트가 비활성화된 상태에서는 호출되지 않습니다. 게임 오브젝트가 활성화될 때 Start()가 호출되며, 한번 호출된 이후로는 게임 오브젝트가 다시 활성화되더라도 재호출되지 않습니다.
Start()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있습니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void Start()
{
// Some initialization code here
}
1.4 FixedUpdate()
FixedUpdate()는 매 물리 프레임마다 호출되며, 주로 물리적인 연산(예를 들어, 리지드바디(Rigidbody)의 움직임을 다루는 것)에 사용됩니다.
Unity의 물리 시스템은 일정한 시간 간격(물리 타임스텝)에 따라 업데이트되며, FixedUpdate() 함수도 이 물리 타임스텝에 맞춰 호출됩니다. 이는 Update() 메서드와 달리 프레임 레이트에 영향을 받지 않기 때문에, 물리 시뮬레이션과 같이 일정한 업데이트 주기가 필요한 작업에 이상적입니다. 예를 들어, Rigidbody 컴포넌트에 힘을 가하는 것은 보통 FixedUpdate() 메서드 내에서 수행합니다. 왜냐하면 이는 Unity의 물리 엔진이 FixedUpdate() 사이의 간격으로 동작하기 때문입니다.
FixedUpdate()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있지 않기 때문에 사용자가 작성해야합니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void FixedUpdate()
{
// Some physics related code here
}
1.5 OnTrigger ___()
OnTrigger___ 메서드들은 Collider 컴포넌트가 트리거 모드로 설정되어 있을 때 호출되며, 물리적인 상호작용을 처리하는데 사용됩니다. 이들 메서드는 모두 매개변수로 Collider 혹은 Collider2D 타입의 객체를 받습니다. (매개 변수, Collider는 추후 글에서 설명합니다.)
1.5.1 OnTriggerEnter()
OnTriggerEnter(): 트리거와 다른 Collider가 처음 겹치기 시작할 때 한 번 호출됩니다. 이 메서드는 트리거에 진입하는 객체를 감지하거나 트리거에 진입하는 순간의 특정 동작을 실행하는 데 유용합니다.
OnTriggerEnter()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있지 않기 때문에 사용자가 작성해야합니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void OnTriggerEnter(Collider other)
{
// Code to execute when an object enters the trigger
}
1.5.2 OnTriggerStay()
트리거와 다른 Collider가 계속 겹쳐 있을 때 매 프레임마다 호출됩니다. 이 메서드는 트리거 내에 객체가 계속 있을 때 실행해야 하는 동작을 처리하는 데 유용합니다.
OnTriggerStay()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있지 않기 때문에 사용자가 작성해야합니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void OnTriggerStay(Collider other)
{
// Code to execute when an object stays in the trigger
}
1.5.3 OnTriggerExit()
트리거와 다른 Collider가 겹치지 않게 될 때 한 번 호출됩니다. 이 메서드는 트리거에서 나가는 객체를 감지하거나 트리거를 떠나는 순간의 특정 동작을 실행하는 데 유용합니다.
OnTriggerExit()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있지 않기 때문에 사용자가 작성해야합니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void OnTriggerExit(Collider other)
{
// Code to execute when an object exits the trigger
}
1.6 OnCollision___()
OnCollision___ 메서드들은 물리적 충돌을 처리하는 데 사용되며, Collider 컴포넌트가 트리거 모드로 설정되어 있지 않을 때 호출됩니다. 이들 메서드는 모두 매개변수로 Collision 혹은 Collision2D 타입의 객체를 받습니다. 이 매개변수는 충돌 이벤트에 대한 정보를 제공합니다. (매개 변수, Collision은 추후 글에서 설명합니다.)
1.6.1 OnCollisionEnter()
두 Collider가 처음 충돌할 때 한 번 호출됩니다. 이 메서드는 충돌이 시작될 때 특정 동작을 실행하거나, 충돌하는 객체를 감지하는 데 사용될 수 있습니다.
OnCollisionEnter()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있지 않기 때문에 사용자가 작성해야합니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void OnCollisionEnter(Collision collision)
{
// Code to execute when the collision starts
}
1.6.2 OnCollisionStay()
두 Collider가 계속 충돌하고 있을 때 매 프레임마다 호출됩니다. 이 메서드는 두 객체가 계속 충돌하고 있을 때 실행해야 하는 동작을 처리하는 데 사용될 수 있습니다.
OnCollisionStay()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있지 않기 때문에 사용자가 작성해야합니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void OnCollisionStay(Collision collision)
{
// Code to execute every frame while the collision continues
}
1.6.3 OnCollisionExit()
두 Collider가 더 이상 충돌하지 않게 될 때 한 번 호출됩니다. 이 메서드는 충돌이 끝나는 순간에 특정 동작을 실행하거나, 충돌이 종료된 것을 감지하는 데 사용될 수 있습니다.
OnCollisionExit()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있지 않기 때문에 사용자가 작성해야합니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void OnCollisionExit(Collision collision)
{
// Code to execute when the collision ends
}
1.7 Update()
Update()는 매 프레임마다 호출되며, 주로 게임 로직, 상태의 업데이트, 사용자 입력의 처리 등을 수행하는데 사용됩니다. 게임이 실행되는 동안 매 프레임에서 호출되므로, 이 메서드 내에서 수행되는 작업은 가능한 한 가볍게 유지해야 합니다. 복잡하고 무거운 작업이 Update() 메서드에 포함되면, 프레임 레이트에 부정적인 영향을 미칠 수 있습니다.
또한, Update() 메서드는 프레임 레이트에 따라 호출 간격이 변할 수 있습니다. 따라서, 프레임 레이트에 종속적이지 않은 부드러운 움직임을 구현하려면 Time.deltaTime을 사용하여 시간 간격을 보정해야 합니다.
Update()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있습니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void Update()
{
// Code to execute every frame
}
1.8 LateUpdate()
LateUpdate()는 매 프레임마다 호출되지만, 일반적인 Update() 메서드가 모두 호출된 이후에 호출됩니다. 주로 Update() 메서드에서 발생한 변화에 따라 후처리를 하는데 사용됩니다. 예를 들어, 카메라를 플레이어 캐릭터가 이동한 후의 위치에 따라 움직이게 하려면, LateUpdate()에서 카메라의 위치를 조정하면 됩니다. 이렇게 하면 Update() 메서드에서 플레이어 캐릭터가 이동한 후에 카메라가 움직이게 됩니다.
LateUpdate()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있지 않기 때문에 사용자가 작성해야합니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void LateUpdate()
{
// Some code here to execute after all Update methods
}
1.9 OnDisable()
OnDisable()는 해당 게임 오브젝트나 그에 연결된 스크립트가 비활성화될 때 호출됩니다. 유니티에서 이벤트의 해제, 리스너의 제거, Coroutine의 정지 등의 작업에 주로 사용됩니다. 이 메서드는 게임 오브젝트나 스크립트가 활성화에서 비활성화로 전환될 때마다 호출되기 때문에, 비활성화 시 필요한 정리 작업을 수행하는 데 적합합니다.
OnDisable()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있지 않기 때문에 사용자가 작성해야합니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void OnDisable()
{
// Some disabling code here
}
게임 오브젝트의 활성화 상태는 인스펙터 패널에서 체크 박스를 통해 제어할 수 있으며, 스크립트에서는 gameObject.SetActive(true) 또는 gameObject.SetActive(false)와 같은 메서드를 사용하여 제어할 수 있습니다. 이런 방법으로 게임 오브젝트나 스크립트의 활성화 상태를 변경하면, OnEnable() 또는 OnDisable() 메서드가 호출됩니다.
1.10 OnDestroy()
OnDestroy()는 게임 오브젝트나 스크립트가 Destroy() 메서드에 의해 제거되기 직전에 호출됩니다. 주로 필요한 정리 작업을 수행하는 데 사용됩니다. 예를 들어, 이 메서드 내에서 사용한 리소스의 해제, 연결의 해제, 이벤트 핸들러의 제거 등을 수행할 수 있습니다. 또한, 게임 오브젝트가 파괴되는 시점에 특정 행동을 실행하기 위해 이 메서드를 사용할 수도 있습니다.
OnDestroy()는 아래와 같은 형태로 사용하며, 스크립트에 기본적으로 처음에 생성되어 있지 않기 때문에 사용자가 작성해야합니다. 이 메서드는 직접 호출되지 않으며, 자동으로 호출됩니다.
void OnDestroy()
{
// Cleanup code here
}
Destroy() 메서드를 사용하여 게임 오브젝트나 컴포넌트를 파괴하는 방법은 다음과 같습니다. 이렇게 Destroy() 메서드를 호출하면, 해당 게임 오브젝트나 컴포넌트가 파괴되기 직전에 OnDestroy() 메서드가 호출됩니다.
// Destroy an object immediately
Destroy(gameObject);
// Destroy an object after a delay
Destroy(gameObject, 5f); // Destroys the object after 5 seconds
1.11 OnApplicationQuit()
OnApplicationQuit()는 유니티 애플리케이션이 종료될 때 호출됩니다. 애플리케이션 종료 전에 실행해야 할 코드를 정의하는 데 사용됩니다. 예를 들어, 게임 진행 상황을 저장하거나, 네트워크 연결을 종료하거나, 사용한 리소스를 정리하는 등의 작업을 수행할 수 있습니다.
OnApplicationQuit() 메서드를 사용하여 게임 오브젝트나 컴포넌트를 파괴하는 방법은 다음과 같습니다. 이렇게 Destroy() 메서드를 호출하면, 해당 게임 오브젝트나 컴포넌트가 파괴되기 직전에 OnDestroy() 메서드가 호출됩니다.
void OnApplicationQuit()
{
// Code to execute when the application is about to quit
}
하지만 OnApplicationQuit() 메서드가 호출되는 시점은 유니티 에디터와 실제 빌드된 애플리케이션에서 다르게 작동할 수 있습니다. 특히 모바일 디바이스에서는 홈 버튼을 눌러 애플리케이션을 백그라운드로 보내는 경우 이 메서드가 호출되지 않을 수 있습니다. 이런 상황에서는 OnApplicationPause() 메서드를 함께 사용해야 할 수 있습니다.