개발 TIL

내일배움캠프TIL 59일차 트러블 슈팅

yun-wj1126 2025. 4. 16. 22:02

Json을 Scriptable Object로 변환하는 과정에서 윈도우 에디터로 커스텀에디터를 만들어서 사용하는 과정에서 윈도우 에디터를 사용시 MonoBehaviour를 상속받지 못해 코루틴을 사용할 수 없는 문제가 발생함

시도 1. 찾아보니 EdiorCoroutine 패키지가 있어서 다운받은 후 using Unity.EdiotrCoroutines.Editor; 를 사용

결과 : EditorCoroutineUtility.StartCoroutineOwnerless(코루틴) 을 사용해서 코루틴이 정상적으로  실행이됨

 

JsonUtility는 배열을 단독으로 파싱하지 못해서 배열 Json을

JsonUtility.FromJson<ItemDataArray>("{\"items\":" + jsonText + "}") 이런식으로 래퍼클래스를 만들고 배열을 감싸는 키로 Json을 감싸야 한다고 해서 이렇게 했는데 문제가 발생함

문제는 이렇게 긴 오류가 나왔는데  87번째 줄에서 참조 타입 변수가 null인데 멤버에 접근하려고 해서 발생

NullReferenceException: Object reference not set to an instance of an object
DownLoader.ConvertJsonToSO () (at Assets/02_Scripts/Item/DownLoader.cs:87)
DownLoader.OnGUI () (at Assets/02_Scripts/Item/DownLoader.cs:48)
UnityEditor.HostView.InvokeOnGUI (UnityEngine.Rect onGUIPosition) (at <5e6ebaa7d75c4d5399dc81ecead6b43f>:0)
UnityEditor.DockArea.DrawView (UnityEngine.Rect dockAreaRect) (at <5e6ebaa7d75c4d5399dc81ecead6b43f>:0)
UnityEditor.DockArea.OldOnGUI () (at <5e6ebaa7d75c4d5399dc81ecead6b43f>:0)
UnityEngine.UIElements.IMGUIContainer.DoOnGUI (UnityEngine.Event evt, UnityEngine.Matrix4x4 parentTransform, UnityEngine.Rect clippingRect, System.Boolean isComputingLayout, UnityEngine.Rect layoutSize, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, UnityEngine.Matrix4x4 worldTransform, UnityEngine.Rect clippingRect, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, System.Boolean canAffectFocus) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.IMGUIContainer.SendEventToIMGUIRaw (UnityEngine.UIElements.EventBase evt, System.Boolean canAffectFocus, System.Boolean verifyBounds) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.IMGUIContainer.SendEventToIMGUI (UnityEngine.UIElements.EventBase evt, System.Boolean canAffectFocus, System.Boolean verifyBounds) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.IMGUIContainer.ProcessEvent (UnityEngine.UIElements.EventBase evt) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.CallbackEventHandler.HandleEvent (UnityEngine.UIElements.EventBase evt) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.CallbackEventHandler.HandleEventAtCurrentTargetAndPhase (UnityEngine.UIElements.EventBase evt) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.CallbackEventHandler.HandleEventAtTargetPhase (UnityEngine.UIElements.EventBase evt) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.MouseCaptureDispatchingStrategy.DispatchEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.EventDispatcher.ApplyDispatchingStrategies (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel, System.Boolean imguiEventIsInitiallyUsed) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.EventDispatcher.ProcessEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.EventDispatcher.ProcessEventQueue () (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.EventDispatcher.OpenGate () (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.EventDispatcherGate.Dispose () (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.EventDispatcher.ProcessEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.EventDispatcher.Dispatch (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel, UnityEngine.UIElements.DispatchMode dispatchMode) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.BaseVisualElementPanel.SendEvent (UnityEngine.UIElements.EventBase e, UnityEngine.UIElements.DispatchMode dispatchMode) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.UIElementsUtility.DoDispatch (UnityEngine.UIElements.BaseVisualElementPanel panel) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.UIElementsUtility.UnityEngine.UIElements.IUIElementsUtility.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr, System.Boolean& eventHandled) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.UIEventRegistration.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.UIElements.UIEventRegistration+<>c.<.cctor>b__1_2 (System.Int32 i, System.IntPtr ptr) (at <383db090fd544f24b368fd389016a28f>:0)
UnityEngine.GUIUtility.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr, System.Boolean& result) (at <d26551307ee24906965335845380d4a1>:0)

 

시도 1. 확인해 보기 위해 data가 null인지 List가 null인지 확인해봄

결과 : data가 null로 뜸

시도 2. data가 null인 것을 확인했고  ItemData클래스와 json의 필드명이 일치하는지 확인해봄

결과 : 일일히 확인해본 결과 같음

시도 3. 순서는 상관있는지 몰라서 찾아보니 순서는 상관없었음 그래서 enum값이 문제인지 찾아봄

결과 : JsonUtility는 enum필드를 int값으로만 직렬화/역직렬화 함 그래서 구글시트에서 정수로 해야했음

그러나 이렇게 되면 바꿔야 하는 부분이 무수히 많이 생겨서 다른방법을 찾아봄

시도 4. 원인이 뭔지 알아냈으니 처리하기 위해 찾아보니 newtonsoft.Json이라는 외부 라이브러리가 있어서 설치

결과 : 결과적으로는 간단하게 해결후 scriptable object로 정상적으로 변환이됨

과정 :

1. Newtonsoft 설치

패키지 매니저에 com.unity.nuget.newtonsoft-json 작성후 추가 하면 설치

 

2. ItemData 클래스에 using Newtonsoft.Json.Converters; 선언 후 

enum 위에  [JsonConverter(typeof(StringEnumConverter))] 작성

 

3.Newtonsoft를 사용시 배열을 래핑하지않아도 바로 파싱가능

List<ItemData> itemList = JsonConvert.DeserializeObject<List<ItemData>>(jsonText);을 사용해서 간단하게 파싱 가능하다. 따로 래핑하지 않아도 괜찮다.

그리고 enum을 2번 처럼 converters로 만들어놔서 enum을 문자열로 파싱가능하다.

 

코드를 바꾸고 다시 실행하니

validCastException: Null object cannot be converted to a value type.
Newtonsoft.Json.JsonSerializationException: Error converting value {null} to type 'System.Int32'. Path '.effect_id', line 1, position 202 가 나옴

JSON 데이터 중 effect_id가 null인데, C# 클래스에서는 int(혹은 다른 non-nullable value type)로 선언되어 있어서 역직렬화가 실패 한것이였다.

시도 1. nullable 타입을 사용할려 했지만 저번에 트러블슈팅에서 말한것처럼 인스펙터에 나오지않는 문제가 발생한다. 그래서 저번에 정한것 처럼 -1을 null 대신 사용하고 구글 시트에 int값중 비어있는 곳에 -1을 채워놓음

결과 : 정상적으로 작동