如何在 Unity3D 中逐个获取请求结果?



我正在使用UnityWebRequest从API获取搜索结果的JSON数组。与其屈服直到返回整个数组,我可以让我的代码一一处理结果吗?

任何方向都值得赞赏。

下面是一些代码:

public IEnumerator GetMovies(string q)
{
string uri = "http://www.omdbapi.com/?apikey=__&s=" + q;
using (UnityWebRequest r = UnityWebRequest.Get(uri))
{
yield return r.SendWebRequest();
if(r.isHttpError || r.isNetworkError)
{
Debug.Log(r.error);
}
else
{
SearchInfo info = JsonUtility.FromJson<SearchInfo>(r.downloadHandler.text);
if(info != null)
{
gameObject.GetComponent<EventManager>().onSearchInfoGet(info);
}
}
}
}

把它放在一个线程上

JsonUtility.FromJson

可以从后台线程调用此方法的字符串版本。

所以你可以尝试简单地做一些类似的事情

// A thread save queue
ConcurrentQueue<SearchInfo> callbacks = new ConcurrentQueue<SearchInfo>();
public IEnumerator GetMovies(string q)
{
var uri = "http://www.omdbapi.com/?apikey=__&s=" + q;
using (var r = UnityWebRequest.Get(uri))
{
yield return r.SendWebRequest();
if (r.isHttpError || r.isNetworkError)
{
Debug.Log(r.error);
}
else
{
// start the deserialization task in a background thread
// and pass in the returned string
Thread thread = new Thread(new ParameterizedThreadStart(DeserializeAsync));
thread.Start(r.downloadHandler.text);
// wait until the thread writes a result to the queue
yield return new WaitUntil(()=> !callbacks.IsEmpty);
// read the first entry in the queue and remove it at the same time
if (callbacks.TryDequeue(out var result))
{
GetComponent<EventManager>().onSearchInfoGet(result);
}
}
}
}
// This happens in a background thread!
private void DeserializeAsync(object json)
{
// now it shouldn't matter how long this takes
var info = JsonUtility.FromJson<SearchInfo>((string)json);
// dispatch the result back to the main thread
callbacks.Enqueue(info);
}

也许有更有效的方法可以将单个数据事件调度回主线程,然后是队列......但至少我可以说ConcurrentQueue是线程保存;)


替代(也许(

而不是使用JsonUtility您可以使用例如SimpleJSON,您只需要在Assets某处创建一个包含SimpleJSON.cs内容的 C# 脚本。

假设像这样的 JSON

{
"Search" : [
{
"Title":"AB",
"Year":"1999",
"imdbID":"abcdefg",
"Type":"AB"
},
{
"Title":"IJ",
"Year":"2000",
"imdbID":"abcdefg",
"Type":"IJ"
},
{
"Title":"XY",
"Year":"2001",
"imdbID":"abcdefg",
"Type":"XY"
}
]
}

和你的SearchInfo喜欢

// This you might not need anymore
[System.Serializable] 
public class SearchInfo 
{ 
public MovieSearchInfo[] Search; 
} 
[System.Serializable] 
public class MovieSearchInfo 
{ 
public string Title; 
public string Year; 
public string imdbID;
public string Type; 
}

然后你可以使用它来解析"手动"的类,例如

// Give your IEnumerator a callback parameter
public IEnumerator GetMovies(string q, Action<JSONArray> OnSuccess = null)
{
var uri = "http://www.omdbapi.com/?apikey=__&s=" + q;
using (var r = UnityWebRequest.Get(uri))
{
yield return r.SendWebRequest();
if (r.isHttpError || r.isNetworkError)
{
Debug.Log(r.error);
}
else
{
// Not sure though if this call is faster then
// simply using JsonUtility ...
var N = JSON.Parse(r.downloadHandler.text);
var theJsonArray = N["Search"].Values;
// Now depending on what you actually mean by one-by-one
// you could e.g. handle only one MoveInfo per frame like
foreach (var item in theJsonArray)
{
var movieInfo = new MovieSearchInfo();
movieInfo.Title = item["title"];
movieInfo.Year = item["Year"];
movieInfo.imdbID = item["imdbID"];
movieInfo.Type = item["Type"];
// NOW DO SOMETHING WITH IT
// wait for the next frame to continue
yield return null;
}
}
}
}

否则,您也可以签出其他 JSON 库。

最新更新