이번 포스트에서는 유니티 프로젝트에서 발생한 NullReferenceException에 대한 문제 해결 과정을 공유하고자 합니다. 이 문제는 유닛 데이터를 UI에 표시하려는 시도 중 발생했으며, 이를 해결하기 위한 몇 가지 접근 방식을 다루겠습니다.
유닛 데이터를 표시하는 UI_Unit 팝업 창을 열 때 NullReferenceException 오류가 발생했습니다. 구체적인 오류 메시지는 다음과 같습니다:
NullReferenceException: Object reference not set to an instance of an object
UI_Unit.UpdateUnitInfo (Unit unit) (at Assets/Scripts/UI/PopUp/UI_Unit.cs:45)
UnitTile.OnPointerDown (UnityEngine.EventSystems.PointerEventData eventData) (at Assets/Scripts/Stage/Tile/UnitTile.cs:38)
UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerDownHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:43)
UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction1[T1] functor) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:272)
UnityEngine.EventSystems.EventSystem:Update() (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:530)
오류 메시지를 통해 UI_Unit.UpdateUnitInfo 메서드에서 NullReferenceException이 발생한 것을 확인할 수 있었습니다. 이는 UI_Unit 클래스의 UI 요소가 아직 초기화되지 않은 상태에서 UpdateUnitInfo 메서드가 호출되었기 때문입니다. 구체적으로, Init() 메서드가 Start()에서 호출되면서 UI 요소의 바인딩이 늦어져서 발생한 문제였습니다.
문제를 해결하기 위해 두 가지 접근 방식을 시도했습니다:
private void Start()
{
Init();
}
public override void Init()
{
base.Init();
Bind<Button>(typeof(Buttons));
Bind<TMP_Text>(typeof(Texts));
Bind<GameObject>(typeof(GameObjects));
Bind<Image>(typeof(Images));
GetButton((int)Buttons.Btn_Close).gameObject.AddUIEvent((PointerEventData data) => OnButtonClicked(Buttons.Btn_Close, data));
GetButton((int)Buttons.Blocker).gameObject.AddUIEvent((PointerEventData data) => OnButtonClicked(Buttons.Blocker, data));
}
private void OnButtonClicked(Buttons buttonType, PointerEventData data)
{
switch (buttonType)
{
//UIManager.Instance.ShowPopupUI<UI_Unit>();
case Buttons.Btn_Close:
ClosePopupUI();
break;
case Buttons.Blocker:
ClosePopupUI();
break;
}
}
public void UpdateUnitInfo(Unit unit)
{
GetText((int)Texts.TXT_AttackPower).text = unit.AttackRange.ToString();
GetText((int)Texts.TXT_AttackSpeed).text = unit.MoveSpeed.ToString();
}
먼저, UI_Unit 클래스를 다음과 같이 수정했습니다:
private Unit unit;
private void Start()
{
Init();
GetText((int)Texts.TXT_AttackPower).text = unit.AttackRange.ToString();
GetText((int)Texts.TXT_AttackSpeed).text = unit.MoveSpeed.ToString();
}
public override void Init()
{
base.Init();
Bind<Button>(typeof(Buttons));
Bind<TMP_Text>(typeof(Texts));
Bind<GameObject>(typeof(GameObjects));
Bind<Image>(typeof(Images));
GetButton((int)Buttons.Btn_Close).gameObject.AddUIEvent((PointerEventData data) => OnButtonClicked(Buttons.Btn_Close, data));
GetButton((int)Buttons.Blocker).gameObject.AddUIEvent((PointerEventData data) => OnButtonClicked(Buttons.Blocker, data));
}
private void OnButtonClicked(Buttons buttonType, PointerEventData data)
{
switch (buttonType)
{
//UIManager.Instance.ShowPopupUI<UI_Unit>();
case Buttons.Btn_Close:
ClosePopupUI();
break;
case Buttons.Blocker:
ClosePopupUI();
break;
}
}
public void UpdateUnitInfo(Unit unit)
{
this.unit = unit;
}
다음으로, UnitTile 클래스에서 OnPointerDown 이벤트에서 UI_Unit을 올바르게 호출하는 코드를 추가했습니다:
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log($"{num} 번째 타일 터치 ");
// UI_Unit 창을 불러오는 코드
UI_Unit unitWindow = UIManager.Instance.ShowPopupUI<UI_Unit>();
unitWindow.UpdateUnitInfo(SpawnUnit);
}
이번 포스트에서는 유니티에서 발생한 NullReferenceException 오류를 해결하기 위해 Awake와 Start 메서드의 호출 순서를 조정하고, 데이터를 미리 받아오는 방식을 적용하여 문제를 해결하는 과정을 공유했습니다. 유니티 프로젝트에서 UI 요소를 다룰 때 초기화 순서와 데이터 바인딩의 중요성을 잊지 말아야겠습니다.
댓글 영역