콘텐츠로 이동

Unity Project Auditor가 지적하는 GC 할당 코드 정리

Unity Project Auditor로 프로젝트를 분석하면 GC 할당을 일으키는 코드가 Major issues로 분류된다. 지적 항목은 모두 GC Alloc에 관한 것이다. 매 프레임 불필요한 관리 메모리를 할당하면 가비지 컬렉터가 주기적으로 정리 작업을 하고, 그동안 게임이 멈칫하는 스파이크가 생긴다.

  • 원인: 현재 시간대와 일광 절약 시간 정보까지 계산하므로 그만큼 CPU 연산이 더 든다.
  • 대안: 시간대 계산이 필요 없으면 System.DateTime.UtcNow를 쓴다. 게임 내 시간이면 Time.time이나 Time.unscaledTime을 쓴다.
  • 원인: .Where(), .OrderBy(), .ToList() 같은 호출은 내부에서 새 컬렉션을 만들고 함수를 반복 호출해 관리 메모리를 할당하고 CPU 연산도 늘어난다.
  • 대안: Update()처럼 매 프레임 도는 코드에서는 쓰지 않는다. for·foreach로 직접 구현한다.
  • 원인: 호출할 때마다 결과를 담을 새 배열을 만들어 돌려준다.
  • 대안: Awake()나 Start()에서 한 번 호출해 결과를 저장해 두고 재사용한다. 매번 호출해야 하면 미리 만든 리스트를 채워 주는 List<T> 인자 오버로드를 쓴다.
  • 원인: 접근할 때마다 현재 모든 터치 정보를 담은 새 배열을 만든다.
  • 대안: Input.touchCount로 터치가 있는지 먼저 확인하고, for 문에서 Input.GetTouch(i)로 하나씩 가져온다. 둘 다 배열을 할당하지 않는다.
  • 원인: 네이티브(C++) 엔진에 있는 이름을 C#으로 가져오면서 매번 새 문자열을 만든다.
  • 대안: Update()에서 이름을 계속 비교해야 하면 gameObject.CompareTag("Player")처럼 태그를 쓴다. 태그 비교는 문자열을 할당하지 않는다. 이름이 꼭 필요하면 Awake()에서 변수에 저장해 둔다.
  • 원인: int 같은 값 타입이 참조 타입 객체로 변환되면 관리 힙에 메모리가 할당된다.
  • 주요 발생 지점:
    • string.Format("점수: {0}", 123)에서 int가 object로 박싱된다.
    • Debug.Log(myIntValue)(Unity 2021 이전 버전)
    • List<object>에 int나 float를 넣을 때
  • 대안: string.Format 대신 문자열 보간이나 ToString()을 쓴다. List<object> 대신 List<int>처럼 타입이 명확한 제네릭 컬렉션을 쓴다.