【问题标题】:Sending http requests in C# with Unity使用 Unity 在 C# 中发送 http 请求
【发布时间】:2018-02-10 17:31:50
【问题描述】:

如何使用 Unity 在 C# 中发送 HTTP GET 和 POST 请求?

我想要的是:

  • 在 post 请求中发送 json 数据(我使用 Unity 序列化程序,所以不需要 新的,我只想在帖子数据中传递字符串并有能力 将 ContentType 设置为 application/json);
  • 毫无问题地获取响应代码和正文;
  • 在不阻塞 UI 渲染的情况下异步执行所有操作。

我尝试过的:

  • 用HttpWebRequest/HttpWebResponse实现,但是太难了,水平太低了(如果找不到更好的,我就得用了);
  • 使用unity WWW,但不符合我的要求;
  • 使用来自 NuGet 的一些外部包 - Unity 不接受它们 :(

大多数问题都与线程有关,我在 C# 中没有足够的经验。 我使用的 IDE 是 Intellij Rider。

【问题讨论】:

  • 使用HttpClient
  • 如果你想做这个异步,你应该使用Unity提供的WWWIEnumerator,如果不是你想要的,那就自己写HttpClient 有线程,但是比较复杂
  • HTTP 客户端可以统一异步完成。
  • 您可以将 NuGet 包与 Unity 一起使用,请参阅此开源插件以使用 Promise 代替 Coroutines github.com/proyecto26/RestClient

标签: c# http unity3d


【解决方案1】:

WWW API 应该可以完成这项工作,但 UnityWebRequest 替换了它,所以我将回答较新的 API。这真的很简单。您必须使用协程通过 Unity 的 API 执行此操作,否则您必须使用 C# 标准 Web 请求 API 和线程之一。使用协程,您可以在完成之前产生请求。这不会阻塞主线程或阻止其他脚本运行。

注意

对于下面的示例,如果您使用低于 Unity 2017.2 的任何内容,请将 SendWebRequest() 替换为 Send(),然后将 isNetworkError 替换为 isError。这将适用于较低版本的 Unity。此外,如果您需要以二进制形式访问下载的数据,请将uwr.downloadHandler.text 替换为uwr.downloadHandler.data。最后使用SetRequestHeader函数设置请求的header。

GET 请求

void Start()
{
    StartCoroutine(getRequest("http:///www.yoururl.com"));
}

IEnumerator getRequest(string uri)
{
    UnityWebRequest uwr = UnityWebRequest.Get(uri);
    yield return uwr.SendWebRequest();

    if (uwr.isNetworkError)
    {
        Debug.Log("Error While Sending: " + uwr.error);
    }
    else
    {
        Debug.Log("Received: " + uwr.downloadHandler.text);
    }
}

带有表单的 POST 请求

void Start()
{
    StartCoroutine(postRequest("http:///www.yoururl.com"));
}

IEnumerator postRequest(string url)
{
    WWWForm form = new WWWForm();
    form.AddField("myField", "myData");
    form.AddField("Game Name", "Mario Kart");

    UnityWebRequest uwr = UnityWebRequest.Post(url, form);
    yield return uwr.SendWebRequest();

    if (uwr.isNetworkError)
    {
        Debug.Log("Error While Sending: " + uwr.error);
    }
    else
    {
        Debug.Log("Received: " + uwr.downloadHandler.text);
    }
}

带有 Json 的 POST 请求

 void Start()
 {
     StartCoroutine(postRequest("http:///www.yoururl.com", "your json"));
 }

 IEnumerator postRequest(string url, string json)
 {
     var uwr = new UnityWebRequest(url, "POST");
     byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(json);
     uwr.uploadHandler = (UploadHandler)new UploadHandlerRaw(jsonToSend);
     uwr.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
     uwr.SetRequestHeader("Content-Type", "application/json");

     //Send the request then wait here until it returns
     yield return uwr.SendWebRequest();

     if (uwr.isNetworkError)
     {
         Debug.Log("Error While Sending: " + uwr.error);
     }
     else
     {
         Debug.Log("Received: " + uwr.downloadHandler.text);
     }
 }

带有 Multipart FormData/Multipart Form File 的 POST 请求

void Start()
{
    StartCoroutine(postRequest("http:///www.yoururl.com"));
}

IEnumerator postRequest(string url)
{
    List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
    formData.Add(new MultipartFormDataSection("field1=foo&field2=bar"));
    formData.Add(new MultipartFormFileSection("my file data", "myfile.txt"));

    UnityWebRequest uwr = UnityWebRequest.Post(url, formData);
    yield return uwr.SendWebRequest();

    if (uwr.isNetworkError)
    {
        Debug.Log("Error While Sending: " + uwr.error);
    }
    else
    {
        Debug.Log("Received: " + uwr.downloadHandler.text);
    }
}

PUT 请求

void Start()
{
    StartCoroutine(putRequest("http:///www.yoururl.com"));
}

IEnumerator putRequest(string url)
{
    byte[] dataToPut = System.Text.Encoding.UTF8.GetBytes("Hello, This is a test");
    UnityWebRequest uwr = UnityWebRequest.Put(url, dataToPut);
    yield return uwr.SendWebRequest();

    if (uwr.isNetworkError)
    {
        Debug.Log("Error While Sending: " + uwr.error);
    }
    else
    {
        Debug.Log("Received: " + uwr.downloadHandler.text);
    }
}

删除请求

void Start()
{
    StartCoroutine(deleteRequest("http:///www.yoururl.com"));
}

IEnumerator deleteRequest(string url)
{
    UnityWebRequest uwr = UnityWebRequest.Delete(url);
    yield return uwr.SendWebRequest();

    if (uwr.isNetworkError)
    {
        Debug.Log("Error While Sending: " + uwr.error);
    }
    else
    {
        Debug.Log("Deleted");
    }
}

【讨论】:

  • 就像我说的,UnityWebRequest 被实现为在另一个线程中运行。协程用于等待/让其完成请求。产量意味着等待UnityWebRequest 这是另一个线程完成。它在屈服时不会阻塞主线程。这就是协程很棒的原因。
  • 我的示例展示了如何使用 json 进行 http 请求。如果您按原样复制 json 示例并粘贴到您的编辑器中而不修改它,它应该可以工作。如果您修改它并且它不起作用,请创建一个新问题。在你创建一个新问题之前,我想告诉你我在你的代码中发现的问题。 execute 是一个协程函数,应该像你一样直接调用。应该使用StartCoroutine(execute()) 函数调用它。再看看我的例子。您必须添加yield return uwr.SendWebRequest();,否则您将来会遇到问题。
  • 最后,带有协程(execute)函数的类必须继承自MonoBehaviour,才能使用StartCoroutine函数启动协程函数。你的类不继承自MonoBehaviour。如果您不想从MonoBehaviour 继承,请参阅我的回答here,因为我描述了如何MonoBehaviour 继承。请在回复此评论之前解决所有这些问题。如果您遇到问题,请提出一个新问题,但在该问题中发布您的代码。
  • @Bluetree 是的,它应该可以在 Unity 支持的任何平台上运行。
  • @Bluetree 就在我的回答中。请参阅该秒下的MultipartFormFileSection。看到它的许多构造函数重载here
【解决方案2】:

https://www.patrykgalach.com/2019/04/18/how-to-call-rest-api-in-unity/

请参考此链接最干净的数据播放方式

并且不要使用www 而不是使用UnityWebRequest

【讨论】:

    【解决方案3】:

    使用 HttpClient 和类似的东西:

    public static HttpContent DoPost(object payload, string subPath)
        {
            var httpClient = new HttpClient();
    
            HttpClient.BaseAddress = new Uri(Global.BaseUrl);
            HttpClient.DefaultRequestHeaders.Clear();
            HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // if you're using json service
    
            // make request
            var response = Global.HttpClient.PostAsJsonAsync(subPath.TrimLeadingSlash(), payload).Result;
    
            // check for error
            response.EnsureSuccessStatusCode();
    
            // return result
            return response.Content;
        }
    

    Payload 是一个要序列化为 json 的对象。如果所有请求都去同一个baseUrl,可以全局设置HttpClient,在这里复用

    【讨论】:

    • 看起来很清晰。我会试试看。但是异步执行呢?
    • . 请求结束时的结果是使其同步的原因。如果你删除它,你可以使用任务/等待等
    • 没有找到 HttpClient 类...而且包 System.Net.Http 不存在。
    • 是的......你不能在当前版本的 .NET Framework (3.5) 中使用 Unity 中的 HttClient 类
    • 如果您更改引擎中的设置,Unity 支持 4.5。适用于统一版本 2017.x 及更高版本。
    猜你喜欢
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 2017-11-07
    • 2023-04-02
    • 1970-01-01
    相关资源
    最近更新 更多