에디터에서는 괜찮지만, 빌드 후 실행 시 "Graphics device is null." 오류가 나타날 수 있습니다. 이 오류의 원인은 다양하지만, TMP를 서브스레드에서 제어할 경우 나타날 수 있습니다. 이를 해결하기위해 메인스레드에서 제어할 수 있도록 하는 기능을 구현하였습니다.
💬 서론
- 유니티 빌드 프로그램이 크래시가 난 후 player.log를 살펴보면 다음과같이 stacktrace와 함께 오류가 난 부분이 나타납니다. 이 함수가 호출되는 위치를 메인스레드에서 호출할 수 있도록 구현한 기능을 이용합니다.
Graphics device is null.
TMPro.TextMeshProUGUI:Awake()
UiTab:ToggleLerp(Boolean, Single)
PacketHandler:S_EnterGameHandler(PacketSession, IMessage)
PacketManager:MakePacket(PacketSession, ArraySegment`1, UInt16)
ServerSession:OnRecvPacket(ArraySegment`1)
ServerCore.PacketSession:OnRecv(ArraySegment`1)
ServerCore.Session:OnRecvCompleted(Object, SocketAsyncEventArgs)
System.Net.Sockets.<>c:<.cctor>b__367_10(IAsyncResult)
System.Threading.ThreadPoolWorkQueue:Dispatch()
⚒️ 구현
- 싱글턴으로 Monobehavior을 상속받아 메인스레드에서 Upate를 호출하여 queue의 내용을 꺼내와 함수를 호출합니다.
using UnityEngine;
using System;
using System.Collections.Generic;
public class UnityMainThreadDispatcher : MonoBehaviour
{
private static readonly Queue<Action> _executionQueue = new Queue<Action>();
private static UnityMainThreadDispatcher _instance = null;
public static UnityMainThreadDispatcher Instance
{
get
{
if (_instance == null)
{
_instance = FindObjectOfType<UnityMainThreadDispatcher>();
if (_instance == null)
{
GameObject go = new GameObject("UnityMainThreadDispatcher");
_instance = go.AddComponent<UnityMainThreadDispatcher>();
}
}
return _instance;
}
}
private void Awake()
{
UnityMainThreadDispatcher.Instance.Enqueue(() => Debug.Log("UnityMainThreadDispatcher Active!"));
}
private void Update()
{
lock (_executionQueue)
{
while (_executionQueue.Count > 0)
{
_executionQueue.Dequeue().Invoke();
}
}
}
public void Enqueue(Action action)
{
lock (_executionQueue)
{
_executionQueue.Enqueue(action);
}
}
}
✅ 적용
- 매니저로서 역할을 수행할 수 있도록 Scene에 컴포넌트를 추가해줍니다.
- 오류가 난 부분이 메인스레드에서 호출될 수 있도록 Action타입으로 함수를 호출해줍니다.
/// <summary>
/// 서버에 접속하면 네트워크 매니저가 호출
/// </summary>
public void ConnectedFromServer()
{
UnityMainThreadDispatcher.Instance.Enqueue(() =>
{
// Auth 매니저 활성화
AuthManager.Instance.Init();
// 로딩 탭 비활성화
UiTabCtrl.Clear(1.0f);
});
}
🕹️ Unity Affiliate
- Unity Affiliate Program 파트너로서 아래의 배너를 통해 접속하신 경우 수수료를 받을 수 있습니다.
- 아래 배너의 에셋들은 '실시간 무료 에셋 랭킹'을 나타냅니다.
'unity game modules' 카테고리의 다른 글
[C#] MySqlConnector를 통해 DB와 통신하기 (0) | 2024.01.28 |
---|---|
[유니티] 피해 효과 (Damage effect overlay) (0) | 2023.08.28 |
[유니티] 퀘스트 시스템(5) - 풀사이즈 UI (0) | 2023.04.11 |
[유니티] 퀘스트 시스템(4) - 컴팩트 UI (0) | 2023.04.11 |
[유니티] 퀘스트 시스템(3) - 콘텐츠 매니저 (0) | 2023.04.11 |