马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

9f547f370dcc586bae5ddae68dee88bc.gif

x

本帖最后由 关尔Manic 于 2019-4-21 14:01 编辑

本文节选自洪流学堂公众号技术专栏《大话Unity2019》,未经允许不可转载。

洪流学堂公众号回复专栏,查看更多专栏文章。洪流学堂,让你快人几步。你好,我是郑洪智。thread-144673-1-1.html

大智:“昨天我们初步了解了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);

}

}

}

我们从上到下来分析这几行代码。Uri类

首先我们用到了System.Uri这个类,这个类可以帮助我们更好的构造uri,特别是在请求本地的file文件时。在请求本地文件时,不同的平台使用的Uri略有不同。

如果不使用Uri类时,各个平台所需要的Uri的字符串示例如下:Windows平台 file:///D:/DATA/StreamingAssets/data.json

WebGl平台 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"));UnityWebRequest

有了Uri以后呢,我们就可以使用UnityWebRequest来进行请求了。

虽然这个叫做WebRequest,但是要记住还可以请求本地的文件哦。UnityWebRequest详解

UnityWebRequest封装了网络请求,支持http、https、file、和匿名ftp协议的请求以及处理。这个类替代了WWW类,相对WWW类使用起来更复杂一些,但是功能和性能也更强大了。

UnityWebRequest类将一个请求分解为了3部分:提供请求时的输出,传输给服务器

从服务器接收数据

控制HTTP的请求流程

UnityWebRequest  由三个元素组成。UploadHandler        处理数据  将数据发送到服务器 的对象

DownloadHandler    从服务器接收数据 的对象

UnityWebRequest      负责 HTTP 通信流量控制来管理上面两个对象的对象。

来说明这些对象之间的关系,如下所示。thread-144673-1-1.html流程图示

对于一次请求,通常的代码流程是:创建一个UnityWebRequest对象

配置UnityWebRequest对象

设置请求的header

设置HTTP的方法(比如GET,POST,HEAD等,自定义HTTP方法除了Android平台,其他平台也都支持)

(可选)创建一个UploadHandler附加到这个UnityWebRequest对象上面

提供上传的数据

提供上传的HTTP表单

(可选)创建一个DownloadHandler附加到这个UnityWebRequest对象上面,如果需要获取返回数据一定要创建

发送Send这个请求

如果是在一个协程里,可以使用yield来返回SendWebRequest(),用于等待请求完成。需要注意的是:如果你之前习惯使用www,一定要注意这个UnityWebRequest在调用SendWebRequest()方法之后才会真正执行请求。

(可选)从DownloadHandler里面读取接收到的数据

(可选)从UnityWebRequest对象读取error信息、HTTP状态码、相应头等信息。UnityWebRequest捷径

小新:“这个UnityWebRequest有点太复杂了吧?没有简单的方法么?”

大智:“这个当然是有的,下面我们来看看之前代码中使用到的Get方法。”使用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;

}

}

}结合协程使用(Coroutine)

之前在69节学习过使用协程,但是这里你会发现使用的方法不太一样了,这里使用的是yield return request.SendWebRequest()。

为什么可以这么写呢?

我可以先告诉你作用是什么:那就是可以等待请求完成后才继续执行。

之前我们学协程的时候使用过yield return new WaitForSeconds(3);

也就是3秒后才继续执行。

在这里呢,UnityWebRequest的请求同样可以通过协程的yield return来等待请求执行完毕,但是不会阻塞主线程。有BOM的问题

假设我们获取到数据后要使用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(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的编码方式,就会报错:thread-144673-1-1.htmlUTF-8 with BOMthread-144673-1-1.html报错

所以一定一定要使用无BOM的UTF8编码的文件。总结UnityWebRequest.Get方法是最简单的,可以代替www使用

UnityWebRequest对象需要调用SendWebRequest之后才会执行请求

一定一定要使用无BOM的UTF8编码的文件今日思考题

大智:“先试着使用上面的代码,获取之前的文件数据试一试!”

小新:“好嘞!”

大智:“收获别忘了分享出来!也别忘了分享给你学Unity的朋友,也许能够帮到他。”

洪流学堂公众号回复专栏,查看更多专栏文章。

Logo

电影级数字人,免显卡端渲染SDK,十行代码即可调用,工业级demo免费开源下载!

更多推荐