https://gist.github.com/20chan/d8def3eb18ae98235decc722ed931ad1
매운 맛 자료
https://ansohxxn.github.io/unitydocs/fakenull/
순한 맛 자료
컴포넌트 하위 클래스의 변수를 public으로 하거나, SerializeField 속성을 부여하면, 인스펙터에 노출되는데,
이 때 해당 변수 초깃값 null이 제대로 세팅되지 않는 현상을 자주 보았다.
null인데... null이 아닌?
왠지 찾아보다가 변수가 인스펙터에 노출되면서 fake null이 세팅되기 때문이라는데
(유니티 인스펙터가 순수 null을 비허용)
자세한 것은 위 두 블로그에 잘 정리되어있는 거 같다
내용을 요약하면,
유니티 엔진 내부는 C++이고, 유니티 엔진 위는 C#으로 작성한다.
우리가 어느 객체를 생성하게 되면
C++ 네이티브 객체가 생성되고, 이를 C# 객체로 참조하는 느낌이라고 보면 된다.
그래서 보통 우리가 원하는 null이 되려면 실제 네이티브 객체도 null이고, C# 객체도 null이어야 할 것이다.
이 동기화가 맞지 않는 경우가 생기는 것이 내가 겪은 SerializeField 이슈였다.
fake null 이슈 중 가장 대표적인 것들이 SerializeField와 UnityEngine.Object.Destroy인 듯함
SerializeField의 경우는 바로 null 포인터를 가진 빈 참조(fake null)가 생성되는 것이고,
Destroy는 C++ 네이티브 객체를 가리키는 포인터를 바로 null로 세팅하며 해제가 가능하지만,
C# 객체 해제는 가비지 컬렉터에 의탁하기 때문에 생기는 현상이다.
평소에는 큰 문제가 없겠지만, 특정 객체가 null인가? 를 확인할 때 좀 위험해보인다.
대체로 UnityEngine.Object끼리 비교할 때는 operator들이 오버로드돼있어서 위험하지야 않겠지만,
IDE로 UnityEngine.Object null 체크를 해보면, fake null과 null의 표기가 다르기 때문에,
이 구별을 위해 operator 안에서 객체를 캐스팅해대면서 비교한다고 한다. (비용 큼)
심지어 ?? 등의 null 비교 연산자는 오버로드가 안돼있단다.
UnityEngine.Object에 대해 C# operator를 사용할 때는 좀 주의해야겠다.
'Unity' 카테고리의 다른 글
[Unity] 포스트 프로세싱? (0) | 2022.06.11 |
---|---|
[Unity] 어드레서블, 에셋 번들 관련 참고 자료 모음 (0) | 2022.06.06 |
[Unity] ExecuteInEditMode (0) | 2022.03.08 |
[Unity] 유니티 Tip 모음 (0) | 2022.02.19 |
[Unity] FormerlySerializedAs (0) | 2022.02.14 |