Unity Version : 2022.3.16f1 LTS 2024 컴퓨터공학과 캡스톤디자인 - Next Reality
UDP 수신
네트워크 매니저를 구축
ublic class NetworkManager : MonoBehaviour
{
private UdpClient udpClient;
private IPEndPoint serverEndPoint;
private Thread receiveThread;
private static NetworkManager instance = null;
// 서버 IP와 포트 설정
public string serverIP = "127.0.0.1";
public int serverPort = 8080;
private void Awake()
{
if (instance != null && instance.gameObject != null)
{
Destroy(instance.gameObject);
return;
}
else
{
Debug.Log("Network Manager Instantiate");
// 서버 설정
serverEndPoint = new IPEndPoint(IPAddress.Parse(serverIP), serverPort);
// 포트 자동으로 만듬
udpClient = new UdpClient();
}
instance = this;
}
public static NetworkManager Instance
{
get
{
if (null == instance)
{
return null;
}
return instance;
}
}
void Start()
{
// 수신 쓰레드 시작
receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.IsBackground = true;
receiveThread.Start();
Thread.Sleep(10);
// SendMessage("PlayerJoin$testID;638506752265295630;testNickname;125");
}
public new void SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
udpClient.Send(data, data.Length, serverEndPoint);
}
void ReceiveData()
{
while (true)
{
try
{
byte[] data = udpClient.Receive(ref serverEndPoint);
string message = Encoding.UTF8.GetString(data);
Debug.Log("Received: " + message);
// 수신한 메시지를 메인 스레드에서 처리할 수 있도록 전달
MainThreadDispatcher.Instance().Enqueue(() => HandleReceivedMessage(message));
}
catch (Exception e)
{
Debug.LogError("Exception: " + e.ToString());
}
}
}
void HandleReceivedMessage(string message)
{
// 수신한 메시지 처리
Debug.Log("Handle on main thread: " + message);
Managers.BroadcastHandler.InvokeEvent(message);
}
void OnApplicationQuit()
{
receiveThread.Abort();
udpClient.Close();
}
}
Main Thread Dispathcher
수신한 메시지를 처리하려고 하는데, 제대로 실행이 안되는 문제가 있었음. 이에 대해 찾아보니 메인 스레드가 아니면 유니티 API에 접근할 수 없다는 정보를 알게 됨 이를 해결하기 위해 다른 스레드에서 메인 스레드로 작업을 위임하도록 하는 디스패처를 사용하게 됨
public class MainThreadDispatcher : MonoBehaviour
{
private static readonly Queue<Action> _executionQueue = new Queue<Action>();
private static MainThreadDispatcher _instance = null;
public static MainThreadDispatcher Instance()
{
if (!_instance)
{
throw new Exception("MainThreadDispatcher not found in scene. Please ensure it is added to the scene.");
}
return _instance;
}
private void Awake()
{
if (_instance == null)
{
_instance = this;
}
else if (_instance != this)
{
Destroy(gameObject);
}
}
public void Enqueue(Action action)
{
lock (_executionQueue)
{
_executionQueue.Enqueue(action);
}
}
private void Update()
{
lock (_executionQueue)
{
while (_executionQueue.Count > 0)
{
_executionQueue.Dequeue().Invoke();
}
}
}
}