private void CheckAndNotifyEndOfVoting(string scoreType)
{
Debug.Log("CheckAndNotifyEndOfVoting check in task Is Completed");
var roomRef = databaseReference.Child(GameManager.Instance.GetRoomCode()).Child(scoreType);
roomRef.GetValueAsync().ContinueWith(task =>
{
if (task.IsCompleted)
{
DataSnapshot snapshot = task.Result;
int currentCount = int.Parse(snapshot.Value.ToString());
Debug.Log($"currentCount : {currentCount}");
if (currentCount == GameManager.Instance.GetPlayerMaxNumber())
{
foreach (Player player in PhotonNetwork.PlayerList)
{
try
{
photonView.RPC("ReceiveVotingEndSign", player);
}
catch (Exception e)
{
Debug.LogError($"Error: {e.Message}");
}
}
}
}
});
}
위의 코드는 플레이어가 투표를 진행하고, 전체 투표 수를 Firebase를 통해 집계하여 방 최대 플레이어와 동일한 수가 되면 모두가 투표에 참여했다고 간주하고 photonView.RPC("ReceiveVotingEndSign", player)를 실행한다.
하지만, 본문 제목에서 확인할 수 있는 이름의 오류가 발생한다. 이는, 해당 함수나 API가 메인 스레드가 아닌 다른 스레드에서 호출 되었기 때문이다. Unity의 네트워크 관련 함수를 Firebase의 ContinueWith 메서드 내에서 호출하였기 때문에 발생하는 오류이다.
이는 메인 스레드에서 실행될 작업을 큐에 저장하고 실행할 수 있는 메인 스레드 디스패처를 구현하고, 이를 오류가 발생하는 부분에서 활용해주는 방법이다. 코드는 다음과 같다.
private void CheckAndNotifyEndOfVoting(string scoreType)
{
Debug.Log("CheckAndNotifyEndOfVoting check in task Is Completed");
var roomRef = databaseReference.Child(GameManager.Instance.GetRoomCode()).Child(scoreType);
roomRef.GetValueAsync().ContinueWith(task =>
{
if (task.IsCompleted)
{
DataSnapshot snapshot = task.Result;
int currentCount = int.Parse(snapshot.Value.ToString());
Debug.Log($"currentCount : {currentCount}");
if (currentCount == GameManager.Instance.GetPlayerMaxNumber())
{
UnityMainThreadDispatcher.Enqueue(() =>
{
foreach (Player player in PhotonNetwork.PlayerList)
{
try
{
photonView.RPC("ReceiveVotingEndSign", player);
}
catch (Exception e)
{
Debug.LogError($"Error: {e.Message}");
}
}
});
}
}
});
}
문제가 발생하는 부분을 UnityMainThreadDispatcher.Enqueue(() => {}); 내부에 넣어준 것을 확인할 수 있다.
using System;
using System.Collections.Generic;
using UnityEngine;
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();
}
}
}
public static void Enqueue(Action action)
{
if (action == null)
throw new ArgumentNullException("action");
lock (_executionQueue)
{
_executionQueue.Enqueue(action);
}
}
}