본문 바로가기
Unity/함수

이벤트 함수

by Jinger 2023. 6. 2.

서론

    유니티에는 MonoBehaviour 클래스 메서드로서 이벤트를 호출하는 함수들이 존재한다. 이들은 유니티 사용의 기초이자 게임을 더욱 편하게 만들어주는 존재로서, 이 함수들을 알아보는 시간을 가져보자. 중요한 부분은 Bold체로 강조 되어 있으니 참고바란다.


이벤트 함수 실행 순서

    Unity 스크립트를 실행하면 사전에 지정한 순서대로 여러 개의 이벤트 함수가 실행된다. 아래 다이어그램은 Unity가 스크립트의 수명 주기 동안 이벤트 함수의 순서를 지정하고 반복하는 방법을 요약한 다이어그램이다.


첫 번째 씬 로드

    다음 함수는 씬이 시작할 때(씬에서 오브젝트마다 한 번) 호출된다.

  • Awake: 이 함수는 항상 Start 함수 전에 호출되며 프리팹이 인스턴스화 된 직후에 호출된다. 게임 오브젝트가 시작하는 동안 비활성 상태인 경우 Awake 함수는 활성화될 때까지 호출되지 않는다.
  • OnEnable(오브젝트가 활성화된 경우에만): 오브젝트 활성화 직후 이 함수를 호출한다. 레벨이 로드되거나 스크립트 컴포넌트를 포함한 게임 오브젝트가 인스턴스화될 때와 같이 MonoBehaviour를 생성할 때 이렇게 할 수 있다.

    씬에 추가된 모든 오브젝트에 대해 Start, Update 등 이전에 호출된 모든 스크립트를 위한 Awake 및 OnEnable 함수가 호출된다. 따라서 게임플레이 도중 오브젝트를 인스턴스화될 때는 실행되지 않는다.

    Manager클래스의 Awake에서 DontDestoryOnLoad함수를 많이 사용되는 데, 이때 Destory도 사용해야한다는 점을 주의바란다. DontDestroyOnLoad 함수는 해당 게임 오브젝트를 다른 씬으로 이동할 때 파괴되지 않도록 설정한다. 이렇게 하면 씬 전환을 해도 싱글톤 객체가 유지되는 장점이 있지만, 다시 Manager가 적용된 씬을 로드할 때, 중복 인스턴스 생성되기도 한다. 그렇기에 "if(instance == null)"로 씬에 중복되어 있는 지 확인하고 중복되어 있다면, Destroy(gameObject)를 통해 현재 객체를 파괴한다.

void Awake()
{
     if (instance == null)
     {
        instance = this;
        DontDestroyOnLoad(gameObject);
    }
    else
    {
        Destroy(gameObject);
    }
}

에디터

  • Reset: 오브젝트에 처음 연결하거나 Reset 커맨드를 사용할 때 스크립트의 프로퍼티를 초기화하기 위해 Reset을 호출한다.
  • OnValidate: OnValidate는 오브젝트가 역직렬화될 때를 포함하여 스크립트의 프로퍼티가 설정될 때마다 호출되며, 이는 에디터에서 씬을 열 때와 도메인을 다시 로드한 후와 같이 다양한 시기에 발생할 수 있다.

첫 번째 프레임 업데이트 전

  • Start: 스크립트 인스턴스가 활성화된 경우에만 첫 번째 프레임 업데이트 전에 호출된다.

    씬 에셋에 포함된 모든 오브젝트에 대해 Update 등 이전에 호출된 모든 스크립트를 위한 Start 함수가 호출된다. 따라서 게임플레이 도중 오브젝트를 인스턴스화될 때는 실행되지 않는다.

Start vs Awake

   Awake 함수는 스크립트 초기화에 사용되며, 다른 스크립트와의 상호작용이 필요한 경우에 사용된다. Start 함수는 초기 설정이나 초기화에 사용되며, Awake 함수 이후에 실행되며 다른 오브젝트와의 상호작용을 위한 초기 준비 작업을 할 때 유용하다.


프레임 사이

  • OnApplicationPause: 이 함수는 일시 정지가 감지된 프레임의 끝, 실질적으로는 일반 프레임 업데이트 사이에 호출된다. 게임에 일시정지 상태를 가리키는 그래픽스를 표시하도록 OnApplicationPause 가 호출된 후에 한 프레임이 추가로 실행된다.

업데이트 순서

    게임 로직, 상호작용, 애니메이션, 카메라 포지션의 트랙을 유지할 때, 사용 가능한 몇몇 다른 이벤트가 존재한다. 일반적인 패턴은 Update 함수에 대부분의 작업을 수행하는 것이지만, 사용할 수 있는 다른 함수도 있다.

  • FixedUpdate: FixedUpdate 함수는 일정한 간격으로 호출되는 함수로서, 물리 업데이트에 사용된다. 보통 Update 함수와는 다른 프레임 레이트로 호출되므로 물리 시뮬레이션과 관련된 작업은 FixedUpdate 함수에서 처리하는 것이 좋습니다. FixedUpdate는 프레임 속도와 관계없이 신뢰할 수 있는 타이머를 호출하기 때문에 움직임 계산을 적용할 때 Time.deltaTime 만큼 값을 곱할 필요가 없다.
  • Update: Update 함수는 프레임마다 호출되는 함수로서, 게임 루프의 일부로서 주기적으로 실행된다. Update 함수는 주로 게임 오브젝트의 상태나 동작을 업데이트하고, 사용자 입력에 대응하고, 게임 로직을 처리하는 데 사용된다.
  • LateUpdate:  LateUpdate 함수는 Update 함수 이후에 호출되는 함수로서, 주로 카메라 이동이나 타겟 따라가기와 같은 작업에 사용된다. LateUpdate 함수는 다른 모든 업데이트가 끝난 후에 실행되므로 카메라 이동이나 타겟 따라가기 등을 처리할 때 유용하다.

    일반적으로 순서가 명시적으로 문서화되거나 설정 가능한 경우를 제외하고, 다른 게임 오브젝트에 대해 동일한 이벤트 함수가 호출되는 순서를 사용해서는 안 된다. (플레이어 루프를 보다 세세하게 제어하고 싶으면 PlayerLoop API로 제어할 수 있다.)
   동일한 MonoBehaviour 서브 클래스의 다른 인스턴스에 대해 이벤트 함수가 호출되는 순서를 지정할 수 없다. 예를 들어 한 MonoBehaviour의 Update 함수는 다른 게임 오브젝트(해당 부모 또는 자식 게임 오브젝트 포함)의 동일한 MonoBehaviour에 대해 Update 함수 전후에 호출될 수 있다.
    한 MonoBehaviour 서브 클래스의 이벤트 함수가 다른 서브 클래스의 이벤트 함수 전에 호출되도록 지정할 수 있다(Project Settings 창의 Script Execution Order 패널 사용). 예를 들어 두 개의 스크립트(EngineBehaviour, SteeringBehaviour)가 있는 경우 EngineBehaviour가 항상 SteeringBehaviour 전에 업데이트되도록 스크립트 실행 순서를 설정할 수 있다.


애니메이션 업데이트 루프

    Unity가 애니메이션 시스템을 평가할 때 이러한 함수와 프로파일러 마커가 호출된다.

  • StateMachineBehaviour (OnStateEnter/OnStateUpdate/OnStateExit): 레이어가 최대 3개의 활성 상태(현재 상태, 중단된 상태, 다음 상태)를 가질 수 있다. 이 함수는 OnStateEnter, OnStateUpdate 또는 OnStateExit 콜백을 정의하는 StateMachineBehaviour 컴포넌트가 포함된 각 활성 상태에 대해 호출된다. 제일 먼저 함수가 현재 상태에 대해 호출되고 중단된 상태에 대해 호출된 후 마지막으로 다음 상태에 대해 호출된다. 이 단계는 Controller 컴포넌트(예: AnimatorController 또는 AnimatorOverrideController 또는 AnimatorControllerPlayable)가 애니메이션 그래프에 있을 때에만 발생한다.
    • OnStateMachineEnter: State Machine Update 단계 동안 컨트롤러의 상태 머신이 엔트리 상태를 통과하는 전환을 만들 때 이 콜백이 첫 번째 업데이트 프레임에 대해 호출된다. StateMachine 하위 상태에 대한 전환의 경우에는 호출되지 않는다.
      • 참고: 이 콜백을 StateMachineBehaviour 컴포넌트에 추가하면 멀티스레드 상태 머신 평가가 비활성화된다.
    • OnStateMachineExit: State Machine Update 단계 동안 컨트롤러의 상태 머신이 종료 상태를 통과하는 전환을 만들 때 이 콜백이 마지막 업데이트 프레임에 대해 호출된다. StateMachine 하위 상태에 대한 전환의 경우에는 호출되지 않는다.
      • 참고: 이 콜백을 StateMachineBehaviour 컴포넌트에 추가하면 멀티스레드 상태 머신 평가가 비활성화된다.
  • Fire Animation Events: 마지막 업데이트 시간과 최신 업데이트 시간 사이에 샘플링된 모든 클립에서 모든 애니메이션 이벤트를 호출한다.
  • StateMachineBehaviour(OnStateMove): 이 콜백을 정의하는 StateMachineBehaviour가 포함된 각 활성 상태에 대해 호출된다.
  • OnAnimatorMove: 업데이트 프레임마다 루트 모션을 수정할 수 있도록 각 Animator 컴포넌트에 대해 한 번 호출된다.
  • StateMachineBehaviour(OnStateIK): IK pass가 활성화되어 있는 레이어에서 이 콜백을 정의하는  StateMachineBehaviour 컴포넌트가 포함된 각 활성 상태에 대해 호출된다. 휴머노이드 릭(Humanoid Rig)을 사용하는 경우에만 이 이벤트가 실행된다.
  • OnAnimatorIK: 애니메이션 IK를 설정한다. IK pass가 활성화된 각 애니메이터 컨트롤러 레이어에 대해 한 번 호출된다.
  • WriteProperties: 다른 모든 애니메이션화된 프로퍼티를 메인 스레드에서 씬에 작성한다.

유용한 프로파일 마커

    스크립트 라이프사이클 플로우차트에 표시된 일부 애니메이션 함수는 호출할 수 없는 이벤트 함수이다. 즉, Unity가 애니메이션을 처리할 때 호출되는 내부 함수이다. 이 함수에는 프로파일 마커가 있으므로 프로파일러를 사용하여 프레임에서 Unity가 호출하는 시간을 확인할 수 있다. Unity가 이러한 함수를 호출하는 시간을 알면 호출한 이벤트 함수가 실행된 시간을 정확하게 파악하는 데 도움이 된다. 예를 들어 FireAnimationEvents 콜백에서 Animator.Play를 호출한다고 가정해 보자. State Machine Update 및 Process Graph 함수가 실행된 후에 FireAnimationEvents 콜백이 발동했다는 사실을 알면 애니메이션 클립이 즉시 재생되는 것이 아니라 다음 프레임에서 재생된다는 것을 예측할 수 있다.

  • State Machine Update: 이 단계에서 모든 상태 머신이 실행 시퀀스대로 평가된다. 이 단계는 Controller 컴포넌트(예: AnimatorController 또는 AnimatorOverrideController 또는 AnimatorControllerPlayable)가 애니메이션 그래프에 있을 때에만 발생한다.
    • 참고: 상태 머신 평가는 대개 멀티스레드이지만, 특정 콜백(예: OnStateMachineEnter 및 OnStateMachineExit)을 추가하면 멀티스레딩이 비활성화된다.
  • ProcessGraph: 모든 애니메이션 그래프를 평가한다. 여기에는 평가할 모든 애니메이션 클립에 대한 샘플링과 루트 모션 계산이 포함된다.
  • ProcessAnimation: 애니메이션 그래프의 결과를 블렌딩한다.
  • WriteTransforms: 모든 애니메이션화된 트랜스폼을 워커 스레드에서 씬에 작성한다.
  • IK pass가 활성화된 여러 개의 레이어가 있는 휴머노이드 릭은 여러 개의 WriteTransforms 패스를 가질 수 있다(스크립트 라이프사이클 플로우차트 참조).

렌더링

  • OnPreCull: 카메라가 씬을 컬링하기 전에 호출된다. 컬링은 어떤 오브젝트를 카메라에 표시할지 결정한다. OnPreCull은 컬링 발생 직전에 호출된다.
  • OnBecameVisible/OnBecameInvisible: 오브젝트가 카메라에 표시되거나/표시되지 않을 때 호출된다.
  • OnWillRenderObject: 오브젝트가 표시되면 각 카메라에 한 번 호출된다.
  • OnPreRender: 카메라가 씬 렌더링을 시작하기 전에 호출된다.
  • OnRenderObject: 모든 일반 씬 렌더링이 처리된 후 호출된다. 이 때 커스텀 지오메트리를 그리는 데에 GL 클래스 또는 Graphics.DrawMeshNow를 사용할 수 있다.
  • OnPostRender: 카메라가 씬 렌더링을 마친 후 호출된다.
  • OnRenderImage: 씬 렌더링이 완료된 후 호출되어 이미지의 포스트 프로세싱이 가능하다.
  • OnGUI: GUI 이벤트에 따라 프레임당 여러 번 호출된다. 레이아웃 및 리페인트 이벤트는 우선 처리되며 각 입력 이벤트에 대해 레이아웃 및 키보드/마우스 이벤트가 다음으로 처리된다.
  • OnDrawGizmos: 시각화 목적으로 씬 뷰에 기즈모를 그릴 때 사용된다.

코루틴

    일반적인 코루틴 업데이트는 Update 함수가 반환된 후 실행된다. 코루틴은 주어진 YieldInstruction이 완료될 때까지 실행을 중단(yield)할 수 있는 함수이다. 코루틴의 다른 사용법은 다음과 같다.

  • yield: 코루틴은 모든 Update 함수가 다음 프레임에 호출된 후 계속된다.
  • yield WaitForSeconds: 지정한 시간이 지난 후, 모든 Update 함수가 프레임에 호출된 후 계속된다.
  • yield WaitForFixedUpdate: 모든 FixedUpdate가 모든 스크립트에 호출된 후 계속된다. FixedUpdate 전에 코루틴이 양보하면 현재 프레임의 FixedUpdate 이후에 재개한다.
  • yield WWW: WWW 다운로드가 완료된 후 계속된다.
  • yield StartCoroutine: 코루틴을 연결하고 MyFunc 코루틴이 먼저 완료되기를 기다린다.
void Upate()
{
    yield
    ...
}

필터

    return 키워드를 사용해 "필터 기능"을 수행한다. 필터 기능은 일반적으로 게임 루프 내에서 특정 상황에 따라 특정 조건을 만족하는 경우에만 특정 코드 블록을 실행하고자 할 때 사용된다. 예를 들어, 어떤 조작을 특정 키 입력 시에만 수행하고자 할 때, 특정 상태에 도달한 경우에만 특정 동작을 실행하고자 할 때 등에 활용된다. 필터 기능을 사용하여 코드 실행을 제어함으로써 효율성을 높일 수 있고, 불필요한 계산을 줄일 수 있다.

void Upate()
{
    if(필요한지 확인)
        return; //필터 기능
    ...
}

오브젝트를 파괴할 때

  • OnDestroy: 오브젝트 존재의 마지막 프레임에 대해 모든 프레임 업데이트를 마친 후 이 함수가 호출된다. 오브젝트는 Object.Destroy 또는 씬 종료에 대한 응답으로 파괴될 수 있다.

종료할 때

    다음 함수는 씬의 활성화된 모든 오브젝트에서 호출된다.

  • OnApplicationQuit: 이 함수는 애플리케이션 종료 전 모든 게임 오브젝트에서 호출된다. 에디터에서 사용자가 플레이 모드를 중지할 때 호출된다.
  • OnDisable: 동작이 비활성화되거나 비활성 상태일 때 이 함수가 호출된다.

주섬주섬

  •  Awake, Start, Update, FixedUpdate, LateUpdate는 자주 사용하니 기억하길 바란다.
  • 예시로 든 코드들은 많이 다른 코딩에서도 많이 사용되는 방법으로 많이 연습하고 실전에서 써보자.
  • 그 외의 Bold체는 보면 바로 이해할 수 있도록 기억하길 바란다.

참고

 

이벤트 함수의 실행 순서 - Unity 매뉴얼

Unity 스크립트를 실행하면 사전에 지정한 순서대로 여러 개의 이벤트 함수가 실행됩니다. 이 페이지에서는 이러한 이벤트 함수를 소개하고 실행 시퀀스에 어떻게 포함되는지 설명합니다.

docs.unity3d.com

 

반응형

'Unity > 함수' 카테고리의 다른 글

Instantiate함수  (0) 2023.04.12

댓글