유니티 버전 - 2022.3.17f1
기존 코드와 개선된 코드
기존 씬 전환시 CinemachineConfiner를 교체해주는 로직을 최적화하기 위해 Profiler와 Stopwatch를 이용하였습니다
초기에는 해당 코드를 사용했습니다, FindGameObjectWithTag를 이용하기에 성능적으로 좋지 않을것이라고 판단하여 리펙토링 하였습니다
private void ChangeConfiner(object p_Args)
{
PolygonCollider2D polygonCollider2D = GameObject.FindGameObjectWithTag(Setting.ConfinerTag).GetComponent<PolygonCollider2D>();
CinemachineConfiner2D cinemachineConfiner2D = GetComponent<CinemachineConfiner2D>();
cinemachineConfiner2D.m_BoundingShape2D = polygonCollider2D;
cinemachineConfiner2D.InvalidateCache();
}
addtive 모드로 로드된 씬의 오브젝트의 정보만 필요하다고 생각되어서 로드된 씬의 루트 오브젝트만 가져와서 태그를 비교하도록 개선하였습니다
private void ChangeConfiner(object p_Args)
{
Scene scene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1);
GameObject[] objs = scene.GetRootGameObjects();
foreach (GameObject obj in objs)
{
if (obj.CompareTag(Setting.ConfinerTag))
{
PolygonCollider2D polygonCollider2D = obj.GetComponent<PolygonCollider2D>();
cinemachineConfiner2D.m_BoundingShape2D = polygonCollider2D;
cinemachineConfiner2D.InvalidateCache();
return;
}
}
}
Profiler와 Stopwatch를 이용한 코드 비교 및 최적화
Profiler를 살펴보았을때 최적화 전에는 맵 이동시 GC의 그래프가 아주 가끔씩 크게 나타나는 것을 보았지만 나름의 최적화를 하고나니 GC의 그래프가 크게 튀는 현상을 보지는 못했습니다, 하지만 그래프에서 볼 수 있듯이 좌측은 가로 줄이2개이고 우측은 줄이3개 있는 것을 확인 할 수 있습니다(실행시간이 더 소요)
각 코드에 StopWatch를 이용하여 실행 시간을 측정하여보았습니다
using System.Diagnostics;
private void ChangeConfiner(object p_Args)
{
Stopwatch stopwatch = Stopwatch.StartNew(); // 측정 시작
PolygonCollider2D polygonCollider2D = GameObject.FindGameObjectWithTag(Setting.ConfinerTag).GetComponent<PolygonCollider2D>();
CinemachineConfiner2D cinemachineConfiner2D = GetComponent<CinemachineConfiner2D>();
cinemachineConfiner2D.m_BoundingShape2D = polygonCollider2D;
cinemachineConfiner2D.InvalidateCache();
stopwatch.Stop(); // 측정 종료
UnityEngine.Debug.Log($"실행 시간: {stopwatch.Elapsed.TotalMilliseconds} ms");
}
평균 값을 측정해보니 다음과 같았습니다, 리펙토링한 코드가 오히려 느린것을 확인할 수 있었습니다
이유를 생각해보았을때, FindGameObjectWithTag()는 유니티에서 제공하는 API로 지금까지 많은 최적화를 거쳐와 빠르고 효율적이지만 리펙토링된 코드는 열린 씬의 루트 오브젝트를 전부 확인한 후 배열로 반환하고
태그 비교후 일치하면 GetComponent까지 실행하는 로직이기에, 상대적으로 더 느리게 작동할 수밖에 없습니다, 그래서 다시 FindGameObjectWithTag()를 사용하는 코드로 수정하였습니다
유니티 API의 의존성을 줄이는 것은 중요하지만, 이렇게 실제로 비교를 통해 테스트하고 결과를 뽑아 적절하게 적용하는 것 또한 필요하다고 생각합니다
'코드 및 공부 > 최적화' 카테고리의 다른 글
스프라이트 아틀라스(Sprite Atlas) (0) | 2024.12.23 |
---|---|
카메라 최적화 (0) | 2024.12.23 |
오디오 에셋 최적화 (0) | 2024.12.23 |