[Unity Editor Scripting] EditorStyles null Reference
EditorStyles null Reference
문제점
Editor를 상속받은 클래스의 OnEnable에서 GUIStyle을 사용하려면 NullReference가 발생한다. 무조건은 아니지만, 다시 리로드되는 타이밍에는 직렬화 되지 않은 데이터는 초기화되므로 무조건 다시 NullReference가 발생하는 것 같다.
private void OnEnable()
{
Init();
//SOManagers.instance.hexGridGenerator = new HexGridGenerator(_hCGeneration.HexPrefab);
}
private void Init()
{
_mainHeaderStyle = new GUIStyle(EditorStyles.boldLabel)
{
fontSize = 18, // 원하는 폰트 크기
fixedHeight = 30f, // 원하는 높이
alignment = TextAnchor.MiddleLeft // 텍스트 좌측 정렬
};
_subHeaderStyle = new GUIStyle(EditorStyles.boldLabel)
{
fontSize = 15, // 원하는 폰트 크기
fixedHeight = 20f, // 원하는 높이
alignment = TextAnchor.MiddleLeft // 텍스트 좌측 정렬
};
}
이는 유니티가 싱글톤처럼 다양한 editor style을 관리하기 떄문인데, 안타깝게도 lazy insntantiate가 되진 않는다. 초기화를 처리하는 UpdateSkinCache라는 내부 메서드가 있는데, 이 메서드는 Unity 에디터에서 특정 시점에 자동으로 호출된다.
// UpdateSkinCache
internal static void UpdateSkinCache(int skinIndex)
{
if (GUIUtility.s_SkinMode != 0)
{
if (s_CachedStyles[skinIndex] == null)
{
EditorResources.RefreshSkin();
s_CachedStyles[skinIndex] = new EditorStyles();
s_CachedStyles[skinIndex].InitSharedStyles();
}
s_Current = s_CachedStyles[skinIndex]; // s_Current가 EditorStyle에서 사용하는 싱글톤 변수이다.
EditorGUIUtility.s_FontIsBold = -1;
EditorGUIUtility.SetBoldDefaultFont(isBold: false);
}
}
ScriptableObjects(Custom Editor 또는 Editor windows도 모두 스크립터블 오브젝트)의 OnEnable은 오브젝트가 로드되거나 역직렬화 될 때 바로 호출된다. 따라서 스타일 초기화를 지연시켜 OnGUI / OnInsepctorGUI, OnSceneGUI에서 실제로 필요할 때 수행하도록 해야한다.
해결 방법 1
스타일 초기화를 지연시켜 OnInspectorGUI에서 실제로 필요할 때 호출을 실행할 때는 이미 EditorGUIStyle에 대해 초기화가 끝났을 것이므로 직접적으로 OnInspectorGUI에서 _mainHeaderStyle등을 바로바로 직접 초기화 하거나, 아니면 별도의 클래스로 Style을 관리하여, OnInsepctorGUI안에서 접근만 하도록 만들면 NullReference가 발생할 일은 없을 것이다.
해결 방법 2
간단하게 구현하려면 OnInsepctorGUI에서 스타일 초기화를 그냥 수행하면 되겠지만, OnInspectorGUI 특성 상 여러번 반복 호출되기에 조금 더 깔끔하게 해결하고 싶다. 이를 해결하기 위한 아주 깔끔한 해결책은 사용자 정의 스타일을 관리하기 위해 자신만의 클래스를 만들고, 지연 초기화 기능을 갖춘 싱글톤으로 구현하는 것이다. 지연 초기화는 잘못된 위치에서 싱글톤을 사용할 때 "약간"위험하지만 보통은 잘 작동한다고 한다,
참고 자료
- https://discussions.unity.com/t/editorstyles-null-reference/238470
- https://learn.microsoft.com/en-us/answers/questions/366920/what-is-late-variable-initialization
'유니티에서 게임개발을 추구하면 안되는걸까 > 유니티 에디터 스크립팅' 카테고리의 다른 글
[Unity] 유니티의 직렬화(serialization)와 재귀 문제 회피 (0) | 2024.11.09 |
---|---|
[Unity Editor Scripting] Editor관련 함수 정리 (0) | 2024.10.25 |