게임공장
유니티 null 체크 유의사항 본문
원문 : https://overworks.github.io/unity/2019/07/16/null-of-unity-object.html
- 유니티 오브젝트는 C++로 작성된 네이티브 객체의 래퍼
- Object.Destroy()를 사용하면 제거되지만 C#으로 래핑한 유니티 오브젝트는 GC가 수집하기 전까지 살아있다
- 이 상태를 "fake null" 이라 한다
- 유니티에서 오버로딩된 ==, != 연산자는 네이티브 객체의 존재 여부까지 판단하여 비용이 많이 든다
- Object.Destroy()를 사용하면 제거되지만 C#으로 래핑한 유니티 오브젝트는 GC가 수집하기 전까지 살아있다
void Start()
{
Stopwatch sw = new Stopwatch();
Transform t = transform;
sw.Start();
for (int i = 0; i < 100000000; ++i)
{
t = transform;
}
sw.Stop();
Debug.Log("cache test 1: " + sw.Elapsed);
}
private Transform _cachedTransform;
public Transform cachedTransform
{
get
{
if (_cachedTransform == null)
{
_cachedTransform = transform;
}
return _cachedTransform;
}
}
void Start()
{
Stopwatch sw = new Stopwatch();
Transform t = cachedTransform;
sw.Start();
for (int i = 0; i < 100000000; ++i)
{
t = cachedTransform;
}
sw.Stop();
Debug.Log("cache test 2: " + sw.Elapsed);
}
- 위와 같은 이유로 위 2개의 코드 중 첫번째 코드가 더 빠르다
- 그만큼 오버로딩된 null 체크가 상당한 비용을 발생시키는 것
- public이나 SerializeField로 선언되어 인스펙터에서 노출된 후 바인딩되지 않은 오브젝트는 "fake null" 이다 (주의)
- 해결 방안
- 단순한 캐싱이나 생성된 이후 파괴되지 않을 싱글턴같은 경우에는 닷넷 오브젝트로서 null 비교를 하는 것이 좋다
- object.ReferenceEquals(_cachedObject, null)
- Destroy 한 이후에 오브젝트에 null을 명시적으로 넣어주자
- 주의할 점은 아무 경우에나 닷넷 오브젝트의 null만 비교하면 안된다는 것
- 단순한 캐싱이나 생성된 이후 파괴되지 않을 싱글턴같은 경우에는 닷넷 오브젝트로서 null 비교를 하는 것이 좋다
반응형
'Articles' 카테고리의 다른 글
문자 인코딩 (Character Encoding) (0) | 2024.03.24 |
---|---|
액터 모델을 간단히 알아보자 (0) | 2021.03.18 |
Clean Code Explained – A Practical Introduction to Clean Coding (0) | 2021.03.15 |