【问题标题】:REST in Unity (send messages from webserver to unity)Unity 中的 REST(从网络服务器向统一发送消息)
【发布时间】:2017-08-25 12:27:21
【问题描述】:

有没有办法让一个简单的网络服务器向 Unity 发送消息?

目前,我们正在更新方法中使用UnityWebRequest.Get() 进行GET。代码如下:

// Update is called once per frame
void Update () {
    StartCoroutine(GetData());
}

IEnumerator GetData()
{
    UnityWebRequest uwr = UnityWebRequest.Get(url);
    yield return uwr.Send();

    if (uwr.isError)
    {
        Debug.Log(uwr.error);
    }else
    {
        Debug.Log((float.Parse(uwr.downloadHandler.text) / 100));
        fnumber = ((float.Parse(uwr.downloadHandler.text) / 100));
        transform.position.Set(oldX, fnumber, oldZ);
    }
}

但是,这会引发此错误:

无法解析目标主机

我找到了this 错误报告,其中指出,它会被修复,但似乎并非如此。

那么,有没有办法让服务器向 Unity 发送消息?

谢谢

【问题讨论】:

  • 为什么不直接在不同的线程上打开套接字连接,然后用一些委托来提供 Unity 的线程?
  • 抱歉,您能再解释一下吗?会很棒。
  • 只需创建一个Thread 并在里面使用Socket 连接到您的Web 服务器。然后在 Thread 的 main 方法中简单地发送/接收数据并将它们传输到应用程序的其他部分。
  • 为什么需要在更新中调用它?您将像数百个协程一样同时运行。这可能是一个原因。
  • 因为我们需要尽可能频繁地获取数据。

标签: c# rest unity3d server client


【解决方案1】:

尝试使用 WWW 调用而不是已损坏的 UnityWebRequest。 你用的是什么版本的统一?

【讨论】:

  • 如果您知道确切的错误 - 请告诉我它们是什么。由于我在生产环境中使用 UnityWebRequest 已经有一段时间了,现在它可以处理数百万个请求,并且没有任何问题。
  • 最新版本
【解决方案2】:

这是从 RESTful 服务器获取请求的简单方法:D。

private string m_URL = "https://jsonblob.com/api/d58d4507-15f7-11e7-a0ba-014f05ea0ed4";

IEnumerator Start () {
    var webRequest = new WWW (m_URL);
    yield return webRequest;
    if (webRequest.error != null) {
        Debug.Log (webRequest.error);
    } else {
        Debug.Log (webRequest.text);
    }
}

【讨论】:

    【解决方案3】:

    将我的评论扩展为更具描述性和具体性,我的建议是创建一个简单的Thread,作为与您的服务器的通信管理器。

    首先你必须实现 this class 来调用 Unity 的 UI 线程上的方法。

    当你实现这个时,只需创建一个类:

    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<Message> _messages;
    
        private CommunicationManager()
        {
            _messages = new Queue<Message>();
            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 );
            }
        }
    }
    

    现在你必须创建 MessageMessageResult 对象:

    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<MessageResult> whenCompleted;
    
        public Message(string requestUri, string requestType, Action<MessageResult> 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 <status>
                    Date: <date>
                    <some additional info>
                    Accept-Ranges: bytes
                    Content-Length: <CONTENT_LENGTH>
                    <some additional info>
                    Content-Type: <content mime type>
             */
             // when you receive this all that matters is <CONTENT_LENGTH>
             int contentLength = <CONTENT_LENGTH>;
             byte[] msgBuffer = new byte[contentLength];
             if (s.Receive(msgBuffer) != contentLength )
             {
                 return null;
             }
    
             return new MessageResult(msgBuffer, whenCompleted);
        }
    }
    

    最后创建 MessageResult 对象:

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

    此方法将在您的主应用程序之外运行,因此不会产生任何冻结等。

    要使用它,你可以这样调用:

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

    有关更多信息,请阅读this wikipedia 关于 HTTP 的文章。

    【讨论】:

    • 我喜欢这个。这是唯一的解决方法吗?而不是滚动你自己的webrequest,HttpWebRequest不能解决这个问题吗?
    • 我认为您也可以使用 HttpWebRequest 但尚未检查,因此我无法在答案中使用它。 :)
    猜你喜欢
    • 1970-01-01
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多