본문 바로가기
개발/Unity

Unity) Main Thread Dispactcher (메인 쓰레드에서 사용하기)

by 테샤르 2025. 1. 27.

Main Thread Dispactcher (메인 쓰레드에서 사용하기)

 

Unity 에서 어떤 동작을 다시 하기 위해서는 메인 쓰레드에서 동작을 하지 않으면 문제가 생기는 경우가 종종 생긴다.

확정적으로 Unity의 메인 쓰레드에서 동작하는것을 보장하기 위한 코드이다.

 

반응형

 

< Unity Main Thread Dispactcher >

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Threading.Tasks;

	public class UnityMainThreadDispatcher : MonoBehaviour
	{

		private static readonly Queue<Action> _executionQueue = new Queue<Action>();

		public void Update()
		{
			lock (_executionQueue)
			{
				while (_executionQueue.Count > 0)
				{
					_executionQueue.Dequeue().Invoke();
				}
			}
		}

		/// <summary>
		/// Locks the queue and adds the IEnumerator to the queue
		/// </summary>
		/// <param name="action">IEnumerator function that will be executed from the main thread.</param>
		public void Enqueue(IEnumerator action)
		{
			lock (_executionQueue)
			{
				_executionQueue.Enqueue(() => {
					StartCoroutine(action);
				});
			}
		}

		/// <summary>
		/// Locks the queue and adds the Action to the queue
		/// </summary>
		/// <param name="action">function that will be executed from the main thread.</param>
		public void Enqueue(Action action)
		{
			Enqueue(ActionWrapper(action));
		}

		/// <summary>
		/// Locks the queue and adds the Action to the queue, returning a Task which is completed when the action completes
		/// </summary>
		/// <param name="action">function that will be executed from the main thread.</param>
		/// <returns>A Task that can be awaited until the action completes</returns>
		public Task EnqueueAsync(Action action)
		{
			var tcs = new TaskCompletionSource<bool>();

			void WrappedAction()
			{
				try
				{
					action();
					tcs.TrySetResult(true);
				}
				catch (Exception ex)
				{
					tcs.TrySetException(ex);
				}
			}

			Enqueue(ActionWrapper(WrappedAction));
			return tcs.Task;
		}


		IEnumerator ActionWrapper(Action a)
		{
			a();
			yield return null;
		}


		private static UnityMainThreadDispatcher _instance = null;

		public static bool Exists()
		{
			return _instance != null;
		}

		public static UnityMainThreadDispatcher Instance()
		{
			if (!Exists())
			{
				throw new Exception("UnityMainThreadDispatcher could not find the UnityMainThreadDispatcher object. Please ensure you have added the MainThreadExecutor Prefab to your scene.");
			}
			return _instance;
		}


		void Awake()
		{
			if (_instance == null)
			{
				_instance = this;
				DontDestroyOnLoad(this.gameObject);
			}
		}

		void OnDestroy()
		{
			_instance = null;
		}


	}

 

 

 

Unity 는 많은 작업(예: 게임 객체의 생성, UI 업데이트, 물리 작업 등)을 메인 스레드에서 실행해야 한다.

하지만 비동기 코드나 백그라운드 스레드를 사용하면 메인 스레드에서만 실행 가능한 작업이 보장되기 어렵거나 확실하지 않는 경우에서는 확정적으로 메인 쓰레드에서 동작하기 위해서 사용하면 된다.

 

★★☆☆☆

 

반응형

댓글