유니티 멀티쓰레드 사용시 UI가 아무런 변화가 없을때

2022. 7. 11. 18:43유니티 unity

유니티에 파이어베이스를 연동할 때 UI가 아무런 반응이 없길래 확인해봤는데

파이어베이스는 기본적으로 데이터들을 비동기로 읽기 때문에 UI가 함수들이 제대로 안 먹히는 부분(메인 쓰레드가 아니기때문)이 있습니다.

그렇기때문에 메인쓰레드에서 UI를 처리를 해줘야합니다.

 

코루틴과 bool 값을 이용해서 코루틴 WaitUntil와 같이 사용해서 처리하거나

큐에 액션을 넣어서 처리하는 방법이 있습니다.

 

큐에 액션을 넣어서 처리하는 좋은 자료가 있습니다.

 

https://github.com/PimDeWitte/UnityMainThreadDispatcher

 

GitHub - PimDeWitte/UnityMainThreadDispatcher: A simple, thread-safe way of executing actions (Such as UI manipulations) on the

A simple, thread-safe way of executing actions (Such as UI manipulations) on the Unity Main Thread - GitHub - PimDeWitte/UnityMainThreadDispatcher: A simple, thread-safe way of executing actions (S...

github.com

 

// 사용법
void 함수()
{

    UnityMainThreadDispatcher.Instance().Enqueue(() => 
    {
        Debug.Log ("메인쓰레드에서 UI를 처리합니다");
    });
}        
//또다른 사용방법
        
public IEnumerator ThisWillBeExecutedOnTheMainThread() 
{
	Debug.Log ("메인쓰레드에서 실행됩니다.");
	yield return null;
}
    
public void ExampleMainThreadCall() 
{
	UnityMainThreadDispatcher.Instance().Enqueue(ThisWillBeExecutedOnTheMainThread()); 
}

 

예제 

메인쓰레드가아닌곳에서 게임오브젝트의 포지션을 무작위로 이동시킵니다.

    using System.Threading;
    
    
    private Thread thread;
    public GameObject ob;
    
    
    void Start()
    {                   

        thread = new Thread(() => Run());
        
        thread.Start();
        
        //쓰레드를 생성시키고 실행시킵니다.
    }

    void Run()
    {
        int i = 0;
        Debug.LogFormat("Thread#{0}: 시작", Thread.CurrentThread.ManagedThreadId);        
        while (i<5)
        {
            i++;

            UnityMainThreadDispatcher.Instance().Enqueue(() =>
            {
                ob.transform.position = new Vector3(Random.Range(0, 5f), Random.Range(0, 5f), Random.Range(0, 5f));
            });
            //람다식으로 간단하게 오브젝트를 이동시켰습니다. 
            //일반적으로 사용할 때는 메인 쓰레드가 아니기 때문에 오류가 발생하는데
            //이 함수를 사용하면 따로 메인쓰레드에서 처리합니다.
            
        Debug.LogFormat($"{i}번째 실행"); 
        Thread.Sleep(1000); // 1초 대기
        }
        Debug.LogFormat("Thread#{0}: 종료", Thread.CurrentThread.ManagedThreadId);
        thread?.Abort(); // 사용한 쓰레드 종료 
        thread = null;
    }

    private void OnDisable()
    {
         thread?.Abort();
         thread = null;
    }