【问题标题】:WWW/UnityWebRequest POST/GET request won't return the latest data from server/urlWWW/UnityWebRequest POST/GET 请求不会从服务器/url 返回最新数据
【发布时间】:2018-07-16 01:01:12
【问题描述】:

我正在使用 Unity 创建一个 HoloLens 应用程序,该应用程序必须从 REST API 获取数据并显示它。 我目前正在使用 WWW 数据类型在将从 Update() 函数调用的协程中获取数据并产生返回语句。当我尝试运行代码时,我从 API 获取最新数据,但是当有人将任何新数据推送到 API 时,它不会自动实时获取最新数据,我必须重新启动该应用程序以查看最新数据。 我的代码:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;

public class TextChange : MonoBehaviour {

    // Use this for initialization
    WWW get;
    public static string getreq;
    Text text;
    bool continueRequest = false;

    void Start()
    {
        StartCoroutine(WaitForRequest());
        text = GetComponent<Text>();
    }

    // Update is called once per frame
    void Update()
    {

    }

    private IEnumerator WaitForRequest()
    {
        if (continueRequest)
            yield break;

        continueRequest = true;

        float requestFrequencyInSec = 5f; //Update after every 5 seconds 
        WaitForSeconds waitTime = new WaitForSeconds(requestFrequencyInSec);

        while (continueRequest)
        {
            string url = "API Link goes Here";
            WWW get = new WWW(url);
            yield return get;
            getreq = get.text;
            //check for errors
            if (get.error == null)
            {
                string json = @getreq;
                List<MyJSC> data = JsonConvert.DeserializeObject<List<MyJSC>>(json);
                int l = data.Count;
                text.text = "Data: " + data[l - 1].content;
            }
            else
            {
                Debug.Log("Error!-> " + get.error);
            }

            yield return waitTime; //Wait for requestFrequencyInSec time
        }
    }

    void stopRequest()
    {
        continueRequest = false;
    }
}

public class MyJSC
{
    public string _id;
    public string author;
    public string content;
    public string _v;
    public string date;
}

【问题讨论】:

  • 您不应该像在问题中那样在 Update 函数中调用协程函数。这就像在一秒钟内发出 60 多个请求。我已经在您的问题中解决了这个问题,方法是将其替换为等待然后再次发出请求的代码。如果这不能解决您的问题,请查看我的答案。
  • 你试过解决方案了吗?
  • 是的,它就像一个魅力......

标签: c# unity3d get yield hololens


【解决方案1】:

发生这种情况是因为在服务器上启用了资源缓存。

我知道的三种可能的解决方案

1.Disable 资源缓存在服务器上。 Instructions 对于每个 Web 服务器都是不同的。通常在.htaccess完成。

2。使每个请求具有唯一的时间戳。时间应为Unix 格式。

此方法不适用于 iOS。你很好,因为这是给HoloLens的。

例如,如果您的网址是http://url.com/file.rar,请在末尾附加?t=currentTimecurrentTimeUnix 格式的实际时间。

完整示例网址:http://url.com/file.rar?t=1468475141

代码

string getUTCTime()
{
    System.Int32 unixTimestamp = (System.Int32)(System.DateTime.UtcNow.Subtract(new System.DateTime(1970, 1, 1))).TotalSeconds;
    return unixTimestamp.ToString();
}

private IEnumerator WaitForRequest()
{
    string url = "API Link goes Here" + "?t=" + getUTCTime();
    WWW get = new WWW(url);
    yield return get;
    getreq = get.text;
    //check for errors
    if (get.error == null)
    {
        string json = @getreq;
        List<MyJSC> data = JsonConvert.DeserializeObject<List<MyJSC>>(json);
        int l = data.Count;
        text.text = "Data: " + data[l - 1].content;
    }
    else
    {
        Debug.Log("Error!-> " + get.error);
    }
}

3.Disable 通过在请求中提供和修改Cache-ControlPragma 标头,在客户端 端缓存。

Cache-Control header 设置为max-age=0, no-cache, no-store,然后将Pragma header 设置为no-cache

我建议您使用 UnityWebRequest 而不是 WWW 类来执行此操作。首先,包括using UnityEngine.Networking;

代码

IEnumerator WaitForRequest(string url)
{

    UnityWebRequest www = UnityWebRequest.Get(url);
    www.SetRequestHeader("Cache-Control", "max-age=0, no-cache, no-store");
    www.SetRequestHeader("Pragma", "no-cache");

    yield return www.Send();
    if (www.isError)
    {
        Debug.Log(www.error);
    }
    else
    {
        Debug.Log("Received " + www.downloadHandler.text);
    }
}

【讨论】:

  • 附带说明,您还应该在更新中处理调用。目前,每帧启动了几十个协程。 InvokeRepeating 更合适。
  • @Everts 刚刚注意到,你是对的。我的答案已经很长了,我不想让它更长。我已经修改了他的答案来解决这个问题,并在他的问题下发表评论让他知道这一点。请注意,您不能将所有类型的 Unity Invoke 函数与协程一起使用。 while 循环似乎适用于此。检查他问题中的更新代码,看看我的意思。
  • 创建一个 void 方法来启动协程,然后你就可以使用 InvokeRepeating。
  • 是的,你也可以这样做。 while 循环适用于此的另一个原因是 StartCoroutine 每次调用时都会分配内存。调用一次,让它永远运行。现在唯一的内存分配是您无法阻止的 WWW 类。对于列表List,他可以把它放在while循环之外,然后重新使用它。
  • @ChanibaL 它曾经在 iOS 上工作。有一个 iOS 版本更新使其无法正常工作。我不记得是哪一个,但这是几年前的事了,有一篇关于这个的帖子。我再也找不到了。另外,上次我在 iOS 上尝试时,该方法不起作用。无论如何,这是对 OP 的提醒,以防万一该方法出现问题。
猜你喜欢
  • 2013-04-10
  • 1970-01-01
  • 1970-01-01
  • 2019-10-04
  • 2020-03-09
  • 1970-01-01
  • 2017-03-16
相关资源
最近更新 更多