赞
踩
本文节选自洪流学堂公众号技术专栏《大话Unity2019》,未经允许不可转载。
洪流学堂公众号回复专栏
,查看更多专栏文章。
洪流学堂,让你快人几步。你好,我是郑洪智。
大智:“昨天我们初步了解了UnityWebRequest是做什么用的以及如何使用,今天我们来仔细看一下昨天代码中的几个部分。”
using System.Collections; using System.IO; using UnityEngine; using UnityEngine.Networking; public class GetFileByWebRequest : MonoBehaviour { IEnumerator Start() { var uri = new System.Uri(Path.Combine(Application.streamingAssetsPath, "data.json")); var request = UnityWebRequest.Get(uri.AbsoluteUri); yield return request.SendWebRequest(); if (request.isNetworkError || request.isNetworkError) { Debug.Log(request.error); } else { Debug.Log(request.downloadHandler.text); } } }
我们从上到下来分析这几行代码。
首先我们用到了System.Uri这个类,这个类可以帮助我们更好的构造uri,特别是在请求本地的file文件时。在请求本地文件时,不同的平台使用的Uri略有不同。
如果不使用Uri类时,各个平台所需要的Uri的字符串示例如下:
file:///D:/DATA/StreamingAssets/data.json
http://localhost/StreamingAssets/data.json
jar:file:///data/app/xxx!/assets/data.json
使用Uri类之后,就可以自动帮我们拼接好这些Uri的字符串,一定要记得:
var uri = new System.Uri(Path.Combine(Application.streamingAssetsPath, "data.json"));
有了Uri以后呢,我们就可以使用UnityWebRequest来进行请求了。
虽然这个叫做WebRequest,但是要记住还可以请求本地的文件哦。
UnityWebRequest封装了网络请求,支持http、https、file、和匿名ftp协议的请求以及处理。
这个类替代了WWW类,相对WWW类使用起来更复杂一些,但是功能和性能也更强大了。
UnityWebRequest类将一个请求分解为了3部分:
UnityWebRequest 由三个元素组成。
来说明这些对象之间的关系,如下所示。
对于一次请求,通常的代码流程是:
小新:“这个UnityWebRequest有点太复杂了吧?没有简单的方法么?”
大智:“这个当然是有的,下面我们来看看之前代码中使用到的Get方法。”
获取简单的文本或者二进制数据,可以使用UnityWebRequest.Get方法。这个方法的参数非常简单,只需要传入Uri即可,和之前的WWW类很类似,可以替代WWW类使用:
// 被抛弃的WWW
WWW myWww = new WWW("http://www.myserver.com/foo.txt");
// 使用起来很类似
UnityWebRequest myWr = UnityWebRequest.Get("http://www.myserver.com/foo.txt");
一般使用的方法如下:
using UnityEngine; using System.Collections; using UnityEngine.Networking; public class MyBehaviour : MonoBehaviour { void Start() { StartCoroutine(GetText()); } IEnumerator GetText() { UnityWebRequest www = UnityWebRequest.Get("http://www.my-server.com"); yield return www.SendWebRequest(); if(www.isNetworkError || www.isHttpError) { Debug.Log(www.error); } else { // Show results as text Debug.Log(www.downloadHandler.text); // Or retrieve results as binary data byte[] results = www.downloadHandler.data; } } }
之前在69节学习过使用协程,但是这里你会发现使用的方法不太一样了,这里使用的是yield return request.SendWebRequest()
。
为什么可以这么写呢?
我可以先告诉你作用是什么:那就是可以等待请求完成后才继续执行。
之前我们学协程的时候使用过
yield return new WaitForSeconds(3);
也就是3秒后才继续执行。
在这里呢,UnityWebRequest的请求同样可以通过协程的yield return来等待请求执行完毕,但是不会阻塞主线程。
假设我们获取到数据后要使用json解析,如果你的文件中有bom,就会出现问题。
using System.Collections; using System.IO; using UnityEngine; using UnityEngine.Networking; [System.Serializable] public class Npc { public int Id; public string 名称; public float 血量; public float 攻击力; public float 防御力; } public class Npcs { public Npc[] npcs; } public class GetFileByWebRequest : MonoBehaviour { IEnumerator Start() { var uri = new System.Uri(Path.Combine(Application.streamingAssetsPath, "data.json")); var request = UnityWebRequest.Get(uri); Debug.Log(uri); var www = request.SendWebRequest(); yield return www; if (request.isNetworkError || request.isNetworkError) { Debug.Log(request.error); } else { var jsonStr = request.downloadHandler.text; Debug.Log(jsonStr); var npcs = JsonUtility.FromJson<Npcs>(jsonStr); Debug.Log(npcs.npcs.Length); } } }
你可以尝试下如下的json文件:
{ "npcs": [ { "Id": 1, "名称": "小猴子", "血量": 10, "攻击力": 1, "防御力": 1 }, { "Id": 2, "名称": "大猴子", "血量": 100, "攻击力": 2, "防御力": 2 }, { "Id": 3, "名称": "孙猴子", "血量": 999999, "攻击力": 9999, "防御力": 9999 } ] }
如果使用utf8+bom的编码方式,就会报错:
所以一定一定要使用无BOM的UTF8编码的文件。
大智:“先试着使用上面的代码,获取之前的文件数据试一试!”
小新:“好嘞!”
大智:“收获别忘了分享出来!也别忘了分享给你学Unity的朋友,也许能够帮到他。”
洪流学堂公众号回复专栏
,查看更多专栏文章。
《大话Unity2019》,大智带小新学Unity2019的有趣经历,让你学Unity更简单。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。