본문 바로가기

유니티/프로젝트 최적화

[Unity] 스크립팅 최적화 (2) - GameObject의 문자열 프로퍼티

반응형

GameObject에서 정보 가져오기

유니티 게임오브젝트에서 해당 오브젝트의 정보를 문자열로 알아내는 방법은 두 가지가 있다.

바로 문자열 프로퍼티, tag와 name이다.

 

그런데 유니티 공식 문서에서는 해당 프로퍼티의 사용을 조심하라고 한다.

 

이것이 왜 문제가 된다는 것일까?


문자열 프로퍼티의 전달 방식

문제는 게임오브젝트의 name과 tag가 문자열 객체를 생성한 뒤 전달한다는 것으로부터 출발된다.

이 때문에 비교할 때마다 GC가 할당되고 이는 프레임 드랍으로 이어진다. (아래의 예시에서 GC Spike를 볼 수 있다.)

 

다행히 name은 런타임 중에 자주 사용할 일이 없다.

그러나 tag의 경우 얘기가 다르다. 오브젝트 비교를 위해 흔히 사용되는 것이 tag이다.

그렇다면 이러한 위험성을 감수하고 tag를 꺼내 써야 하는가?

 

유니티는 자주 사용되는 tag를 위해 별도의 메소드를 제작해 두었다.


CompareTag

이 함수는 tag를 비교하기 위한 특별한 메소드이다.

tag는 문자열이기 때문에 ==와 같은 방법으로 비교를 할 수 있으나 CompareTag를 사용하면 GC Allocate와 GC Collect를 막을 수 있다.

 

어떻게 가능한 것일까?

 

유니티가 실행되며 앱이 초기화되는 순간 하드코딩된 문자열을 모두 할당하게 된다. 그리고 런타임 도중에는 단순히 할당된 값들을 참조하기 때문에 별도의 GC가 동작하지 않아도 되는 것이다.


유니티 프로파일링을 통한 비교

아래와 같이 키보드 입력을 통해 각 코드를 1000만 번 실행하며 걸리는 시간을 비교하였다.

소스 코드는 다음과 같다.

using UnityEngine;

public class TagComparisionTest : MonoBehaviour
{
    private int testCount = 10000000;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            Debug.Log("TEST ==");
            for (int i = 0; i < testCount; ++i)
                if (gameObject.tag == "Jsland") { }
        }
        
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            Debug.Log("TEST CompareTag");
            for (int i = 0; i < testCount; ++i)
                if (gameObject.CompareTag("Jsland")) { }
        }
    }
}

 

먼저 ==을 사용한 tag 비교이다.

3628ms 소요

 

다음은 CompareTag를 통한 tag비교이다.

1522ms 소요

 

두 개의 문자열 비교 방식은 두 배가 넘는 큰 차이를 보여준다.

 

특별한 이유가 없다면 GameObject의 name 수정이나 사용은 피하도록 하고 tag의 사용도 CompareTag를 이용하도록 하자.

반응형