Unity

[Unity][서버] 서버 - Unity 연동 (1)

goliot 2024. 6. 17. 00:44
반응형

연동

  • 지금까지 만들어둔 서버를 활용
  • 유니티 프로젝트를 클라이언트로서 사용
  • 그러나 모든 c# 메소드들이 유니티에서 그대로 동작한다는 보장은 없음
  • 우선 프로젝트를 만들어서 ServerCore와 DummyClient를 옮긴다
  • 그리고 PacketHandler를 수정해보자
using ServerCore;
using UnityEngine;
using DummyClient;

class PacketHandler
{
    public static void S_ChatHandler(PacketSession session, IPacket packet)
    {
        S_Chat chatPacket = packet as S_Chat;
        ServerSession serverSession = session as ServerSession;

        if (chatPacket.playerId == 1)
        {
            Debug.Log(chatPacket.chat);

            GameObject go = GameObject.Find("Player");
            if(!go)
            {
                Debug.Log("Player not found");
            }
            else
            {
                Debug.Log("Player found");
            }
        }
    }
}
  • 실행을 해보면, 첫 chat 로그가 뜬 이후로 멈춰버린다
  • 유니티 관련 코드는 메인 쓰레드가 아닌 다른 쓰레드에서 실행되지 못하게 막아져있기 때문!
  • 아래와 같이 해결해보자
    • 패킷을 핸들러로 바로 처리하는 것이 아니라, 큐에다가 밀어서, 유니티 쓰레드에서 처리를 하게 하자
public class NetworkManager : MonoBehaviour
{
    ServerSession _session = new ServerSession();

    void Start()
    {
        //DNS 사용
        string host = Dns.GetHostName(); //내 로컬 컴퓨터의 호스트 이름
        IPHostEntry ipHost = Dns.GetHostEntry(host);
        IPAddress ipAddr = ipHost.AddressList[0];
        IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777); //주소, 포트번호

        Connector connector = new Connector();
        connector.Connect(endPoint,
            () => { return _session; },
            1);

        StartCoroutine(CoSendPacket());
    }

    void Update()
    {
        IPacket packet = PacketQueue.Instance.Pop();
        if(packet != null)
        {
            PacketManager.Instance.HandlePacket(_session, packet);
        }
    }

    IEnumerator CoSendPacket()
    {
        while(true)
        {
            yield return new WaitForSeconds(1f);

            C_Chat chatPacket = new C_Chat();
            chatPacket.chat = "Hello Unity!";
            ArraySegment<byte> segment = chatPacket.Write();

            _session.Send(segment);
        }
    }
}

public class PacketQueue
{
    public static PacketQueue Instance { get; } = new PacketQueue();

    Queue<IPacket> _packetQueue = new Queue<IPacket> ();
    object _lock = new object ();

    public void Push(IPacket packet)
    {
        _packetQueue.Enqueue (packet);
    }

    public IPacket Pop()
    {
        lock (_lock)
        {
            if (_packetQueue.Count == 0)
                return null;

            return _packetQueue.Dequeue ();
        }
    }
}


class PacketManager
{
    #region Singleton
    static PacketManager _instance = new PacketManager();
    public static PacketManager Instance { get { return _instance; } }
    #endregion

    T MakePacket<T>(PacketSession session, ArraySegment<byte> buffer) where T : IPacket, new()
    {
        T pkt = new T();
        pkt.Read(buffer);
        return pkt;
    }

    public void HandlePacket(PacketSession session, IPacket packet)
    {
        Action<PacketSession, IPacket> action = null;
        if (_handler.TryGetValue(packet.Protocol, out action))
            action.Invoke(session, packet);
    }
}

정상적으로 송수신이 이뤄지는 모습

 

반응형