REST in Unity (send messages from webserver to unity)

后端 未结 3 1166
执笔经年
执笔经年 2021-01-28 05:29

Is there a way to have a simple webserver send messages to Unity?

At the moment, we\'re doing a GET using UnityWebRequest.Get() in the update

3条回答
  •  臣服心动
    2021-01-28 05:53

    Expanding my comment to be more descriptive and concrete, my suggestion is to create a simple Thread that will serve as the communication manager with your server.

    First of all you have to implement this class to call methods on Unity's UI thread.

    When you implement this just create a class :

    public class CommunicationManager
    {
        static readonly object syncRoot = new object();
    
        static CommunicationManager _Instance;
        public static CommunicationManager Instance
        {
            get
            {
                if ( _Instance == null )
                {
                    lock ( syncRoot )
                    {
                        if ( _Instance == null )
                        {
                            _Instance = new CommunicationManager();
                        }
                    }
                }
                return _Instance;
            }
        }
    
        volatile bool working = false;
    
        Queue _messages;
    
        private CommunicationManager()
        {
            _messages = new Queue();
            InitializeCommunication();
        }
    
        void InitializeCommunication()
        {
            Thread t = new Thread(CommunicationLoop);
            t.Start();
        }
    
        void CommunicationLoop()
        {
            Socket s = null;
            try
            {
                Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                s.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1337));
                working = true;
            }
            catch(Exception ex)
            {
                working = false;
            }
            while ( working )
            {
                lock ( syncRoot )
                {
                    while ( _messages.Count > 0 )
                    {
                        Message message = _messages.Dequeue();
                        MessageResult result = message.Process(s);
                        result.Notify();
                    }
                }
                Thread.Sleep(100);
            }
        }
    
        public void EnqueueMessage(Message message)
        {
            lock ( syncRoot )
            {
                _messages.Enqueue( message );
            }
        }
    }
    

    Now you have to make Message and MessageResult objects :

    public class Message
    {
        const string REQUEST_SCHEME = "{0} {1} HTTP/1.1\r\nHost: {hostname}\r\nContent-Length: 0\r\n\r\n";
        string request;
        Action whenCompleted;
    
        public Message(string requestUri, string requestType, Action whenCompleted)
        {
            request = string.Format(REQUEST_SCHEME, requestType, requestUri);
            this.whenCompleted = whenCompleted;
        }
    
        public MessageResult Process(Socket s)
        {
            IPEndPoint endPoint = (IPEndPoint)s.RemoteEndPoint;
            IPAddress ipAddress = endPoint.Address;
            request = request.Replace("{hostname}", ipAddress.ToString());
            s.Send(Encoding.UTF8.GetBytes(request));
    
            // receive header here which should look somewhat like this :
            /*
                    HTTP/1.1 
                    Date: 
                    
                    Accept-Ranges: bytes
                    Content-Length: 
                    
                    Content-Type: 
             */
             // when you receive this all that matters is 
             int contentLength = ;
             byte[] msgBuffer = new byte[contentLength];
             if (s.Receive(msgBuffer) != contentLength )
             {
                 return null;
             }
    
             return new MessageResult(msgBuffer, whenCompleted);
        }
    }
    

    And lastly create MessageResult object :

    public class MessageResult
    {
        Action notifier;
        byte[] messageBuffer;
    
        public MessageResult(byte[] message, Action notifier)
        {
            notifier = notifier;
            messageBuffer = message;
        }
    
        public void Notify()
        {
            UnityThread.executeInUpdate(() =>
            {
                notifier(this);
            });
        }
    }
    

    This method will run aside from your main application so that wont produce any freezes and whatever.

    To use this you can just call something like this :

    Message message = new Message("/index.html", "GET", IndexDownloaded);
    CommunicationManager.Instance.EnqueueMessage(message);
    
    // ...
    public void IndexDownloaded(MessageResult result)
    {
        // result available here
    }
    

    For more informations read this wikipedia article about HTTP.

提交回复
热议问题