본문 바로가기
개발/Unity

Unity) 10000번의 Update 호출

by 테샤르 2019. 12. 6.

Unity 10000번의 Update 호출

 

유니티의 Message System에 대한 설명인데 다들 개발을 하면서 '프레임'에 대한 고민을 많이 할 것이다.

 

유니티는 Update를 호출하기 위해 모든 Behaviours 순회합니다. 

프레임에 대해서는 그냥 단순히 어떤 순서상에 의거해서 계속적으로 Update라는 함수가 호출될 거라고 생각을 하고 작업을 하는데 과연 내부는 어떨까??

 

유니티의 Life Cycle 순서상에 보면 

Object - Awake - OnEnable - Start -FixedUpdate - Update -yield null - yield StartCoroutine -Late Update 순으로 이뤄져 있다.

 

 

Update 문은 어떻게 호출되나? 유니티는 유저의 매직 함수를 한번 호출하기 위해서, 매번 System.Reflection을 이용해 그 함수를 찾지 않는다. 대신, 주어진 MonoBehaviour 스크립트가 처음으로 이용될 때, 스크립트 내 매직 함수들이 있다면 이 스크립트는 각 매직 함수와 연관된 List에 저장됩니다. 예를 들어 어떤 스크립트에 Update 함수가 정의되어 있다면 이 스크립트는 Update와 관련된 List에 저장되고, 이건 매프 레임마다 Update가 호출되어야 할 시점에 사용되는데. 게임이 실행되는 동안 유니티는 이러한 리스트를 순회하면서 실행시킨다. 

이러한 이유 때문에 Update 함수가 public이든 private이든 상관이 없다는 이야기다.

 

 

실제 함수의 호출 순서는어떤 순서로 Update 함수는 호출될까?

호출 순서는 Script Execution Order Settings (menu: Edit > Project Settings > Script Execution Order)을 이용해 결정할 수 있습니다. 

하지만 만개의 스크립트가 있다면, 그걸 일일이 정의하는 건 쉬운 일은 아닐 것입니다. 어떤 스크립트가 다른 모든 스크립트들보다 먼저 실행돼야 하는 경우에는 이 방식이 유용합니다. 물론 미래에는 C#의 속성 기능을 이용한다던가 하는 식의 좀 더 손쉬운 방법이 생기길 원합니다.

 

 

10000번의 Update 호출

출처의 실행결과를 보면 

 

(1) 첫 번째 씬에서는 아래의 코드를 가지는 10000개의 MonoBehaviour가 생성 후

private void Update()

{

       i++;

}

 

(2) 두 번째 씬에서는 또 다른 10000개의 MonoBehaviour들이 생성하고. 하지만 이번에는 스크립트가 Update문을 가지는 게 아니라 UpdateMe라는 함수를 가집니다. 그리고 이 함수는 아래처럼 매니징 스크립트의 Update함수에서 호출을 해보는 결과를 본다.

 

private void Update() {

    var count = list.Count;

    for (var i = 0; i &; count; i++) list[i].UpdateMe();

}

 

Mono에서는 (Fast but no Exception 옵션을 켜지 않을 경우)

Mono (fast but no exceptions 옵션 킨 경우)

IL2CPP

결과적으로는 약 5배의 성능의 차이를 보이게 된다.  왜 매니징 스크립트에서 호출을 하면 더 빨라질까?

좀 더 자세한 내부에 대한 설명은 출처를 참고하면 된다. 결론적으로 말하면 호출 순서상에 의거해서 Update는 모든 Mono를 검사를 하면서 실행을 하게 되는 형태다 보니 Operation에서는 All Behaviours를 찾는 시간이 굉장히 많이 소요된다는 이야기인 것이다. 

 

원문: https://blogs.unity3d.com/kr/2015/12/23/1k-update-calls/

 

★☆

반응형

댓글