UN4L8——UnityWebRequest类
UN4L8——UnityWebRequest类
本章代码关键字
1 | UnityWebRequest //Unity提供的一个模块化的系统类,用于构成HTTP请求和处理HTTP响应,ftp和本地资源也可以用 |
UnityWebRequest
UnityWebRequest
是一个Unity提供的一个模块化的系统类,用于构成HTTP请求和处理HTTP响应
它主要目标是让Unity游戏和Web服务端进行交互,它将之前WWW
的相关功能都集成在了其中
所以新版本中都建议使用UnityWebRequest
类来代替WWW
类,它在使用上和WWW
很类似
与WWW
主要的区别就是UnityWebRequest
把下载下来的数据处理单独提取出来了,我们可以根据自己的需求选择对应的数据处理对象来获取数据
我们可以利用Post
上传数据或上传文件,Put
同样主要用于上传文件,但是必须资源服务器支持Put
请求类型
为了通用性,我们可以统一使用Post
请求类型进行数据和资源的上传,它的使用和之前的WWW
类似,只要前后端制定好规则就可以相互通信了
UnityWebRequest
的上传与下载还可以将数据处理分离开,按照自己的规则处理数据,请见:UN4L9——UnityWebRequest高级操作
注意:
UnityWebRequest
和WWW
一样,需要配合协同程序使用-
UnityWebRequest
和WWW
一样,支持http、ftp、file协议下载或加载资源 -
UnityWebRequest
能够上传文件到HTTP资源服务器
UnityWebRequest类的常用操作
- 使用
Get
请求获取文本或二进制数据 - 使用
Get
请求获取纹理数据 - 使用
Get
请求获取AB包数据 - 使用
Post
请求发送数据 - 使用
Put
请求上传数据
获取相关API
-
Get
创建获取文本或者二进制数据的网络请求1
UnityWebRequest unityWebRequest = UnityWebRequest.Get("http://192.168.43.144/Http_Server/test.txt");
-
Get
创建获取纹理的网络请求1
UnityWebRequest unityWebRequest = UnityWebRequestTexture.GetTexture("ftp://192.168.43.144/下载测试.png");
-
Get
创建获取AB包的网络请求1
UnityWebRequest unityWebRequest = UnityWebRequestAssetBundle.GetAssetBundle("http://192.168.43.144/Http_Server/lua");
-
发送网络请求
发送网络请求,执行下载逻辑,在网络获取的协程内,如果
yield return unityWebRequest.SendWebRequest()
,即可让协程挂起到下载完毕1
2
3
4
5
6
7
8
9
10IEnumerator LoadText()
{
UnityWebRequest unityWebRequest = UnityWebRequest.Get("http://192.168.43.144/Http_Server/test.txt");
yield return unityWebRequest.SendWebRequest();
//如果处理成功,结果就是成功的枚举
if (unityWebRequest.result == UnityWebRequest.Result.Success)
{
print(unityWebRequest.downloadHandler.text);
}
} -
是否下载/上传完毕
1
if (!unityWebRequest.isDone) { }
-
当前下载的字节数
1
print($"下载了{unityWebRequest.downloadedBytes}字节");
-
当前下载的进度(0~1)
1
print($"下载到{unityWebRequest.downloadProgress * 100}%");
-
网络请求结果
当下载完毕后,就可以通过
unityWebRequest.result
判断下载是否成功,如果等于UnityWebRequest.Result.Success
就是下载成功1
2
3
4
5
6
7
8
9
10if (unityWebRequest.result == UnityWebRequest.Result.Success)
{
print(unityWebRequest.downloadHandler.text);
byte[] bytes = unityWebRequest.downloadHandler.data;
print("字节数组长度:" + bytes.Length);
}
else
{
print("获取失败:" + unityWebRequest.result + unityWebRequest.error + unityWebRequest.responseCode);
} -
请求失败时输出原因
如果执行失败,可通过
unityWebRequest.result
、unityWebRequest.error
、unityWebRequest.responseCode
,检查出错原因其中
unityWebRequest.responseCode
是状态码1
print("获取失败:" + unityWebRequest.result + unityWebRequest.error + unityWebRequest.responseCode);
-
下载完毕后获取文本信息
1
print(unityWebRequest.downloadHandler.text);
-
下载完毕后获取二进制数据信息
1
2byte[] bytes = unityWebRequest.downloadHandler.data;
print("字节数组长度:" + bytes.Length); -
下载完毕后获取纹理消息
1
image.texture = DownloadHandlerTexture.GetContent(unityWebRequest);
-
下载完毕后获取AB包消息
1
2AssetBundle ab = DownloadHandlerAssetBundle.GetContent(unityWebRequest);
print(ab.name);
Get获取操作
UnityWebRequest
使用上和WWW
类很类似,我们需要注意的是:
- 获取文本或二进制数据时:使用
UnityWebRequest.Get
- 获取纹理图片数据时:使用
UnityWebRequestTexture.GetTexture
以及DownloadHandlerTexture.GetContent
- 获取AB包数据时:使用
UnityWebRequestAssetBundle.GetAssetBundle
以及DownloadHandlerAssetBundle.GetContent
获取文本和二进制
如果是读取二进制数据或者文本文件内的文本,
需要使用UnityWebRequest.Get()
传入http、ftp、或本地文件地址(file开头)创建一个unityWebRequest
对象
然后yield return unityWebRequest.SendWebRequest()
,发送网络请求后挂起协程
待处理完毕,回到协程,即可使用unityWebRequest.result
检测执行结果,如果为UnityWebRequest.Result.Success
就是执行成功
如果执行成功,文本数据可通过unityWebRequest.downloadHandler.text
获取字符串内容数据
二进制数据可通过unityWebRequest.downloadHandler.data
获取字节数组形式数据
如果执行失败,可通过unityWebRequest.result
、unityWebRequest.error
、unityWebRequest.responseCode
,检查出错原因
1 | void Start() |
获取纹理
纹理(图片)的获取使用UnityWebRequestTexture.GetTexture()
方法传入地址创建一个unityWebRequest
对象,即可挂起协程等待获取完毕
获取完毕后,使用(unityWebRequest.downloadHandler as DownloadHandlerTexture).texture
通过转换获取图片
但是更方便的获取方法是,调用DownloadHandlerTexture.GetContent()
方法,传入unityWebRequest
对象,即可获取图片
注:请不要在同一帧里连续去获取同样的资源,尤其是该资源比较大时,会报503的错误(虽然应该不会傻了去同时获取两次一样的资源)
1 | public RawImage image; |
以下载图片为例,如果想要显示下载进度和下载字节数,直接执行unityWebRequest.SendWebRequest()
然后每帧检测是否下载完毕,然后输出下载进度和下载字节数
1 | IEnumerator LoadTexture() |
获取AB包
纹理(图片)的获取使用UnityWebRequestAssetBundle.GetAssetBundle()
方法传入地址创建unityWebRequest
对象,即可挂起协程等待获取完毕
获取完毕后,使用(unityWebRequest.downloadHandler as DownloadHandlerAssetBundle).assetBundle
通过转换获取AB包
但是更方便的获取方法是,调用DownloadHandlerAssetBundle.GetContent()
方法,传入unityWebRequest
对象,即可获取AB包
1 | void Start() |
上传相关数据类
父接口:IMultipartFormSection
,数据相关类都继承该接口,我们可以用父类装子类
我们在使用Post
发送数据时,经常会发送多个数据,因此我们可以声明一个IMultipartFormSection
的List
来装载不同类型的数据
1 | List<IMultipartFormSection> dataList = new List<IMultipartFormSection>(); |
我们声明这样的List
后,就可以将其子类数据直接添加到列表内,然后将列表一起通过UnityWebRequest
上传到服务器
IMultipartFormSection的子类数据
-
MultipartFormDataSection
,它一般用来传递一些键值对的数据,传递上去的数据需要服务器的后端程序员来处理该类的构造函数有多种重载:
-
二进制字节数组
值得一提的是,我们一般很少直接用二进制字节数组,除非和服务器的后端商量好如何处理字节数组
1
2List<IMultipartFormSection> dataList = new List<IMultipartFormSection>();
dataList.Add(new MultipartFormDataSection(Encoding.UTF8.GetBytes("二进制字节数组测试"))); -
字符串
同样我们需要和服务器的后端商量好如何处理字符串
1
2List<IMultipartFormSection> dataList = new List<IMultipartFormSection>();
dataList.Add(new MultipartFormDataSection("字符串测试")); -
参数名,参数值(字节数组,字符串),编码类型,资源类型(常用)
如果参数值是字符串形式的,第三个参数就可以填入字符编码,第四个参数则是资源类型,如何填参考:ContentType的常用类型
如果参数值是字节数组形式的,第三个参数就是资源类型1
2
3List<IMultipartFormSection> dataList = new List<IMultipartFormSection>();
dataList.Add(new MultipartFormDataSection("Name", "MrTang", Encoding.UTF8, "application/..."));
dataList.Add(new MultipartFormDataSection("Msg", new byte[1024], "application/..."));
-
-
MultipartFormFileSection
,它用来把文件的二进制数据传递到服务器上,相当于传文件,
与以前的WWW
和WWWFrom
上传数据不同,为了适应 Addressables 上传AB包的需要,该类对象传递的文件无需做额外处理就可以直接上传到服务器该类的构造函数同样有多种重载:
-
字节数组
直接传输文件的二进制数据,不常用
1
dataList.Add(new MultipartFormFileSection(File.ReadAllBytes(Application.streamingAssetsPath + "/test.png")));
-
文件名,字节数组(常用)
上传的时候会将文件名一并传输出去
1
dataList.Add(new MultipartFormFileSection("上传的文件名.png", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png")));
-
字符串数据,文件名(常用)
将参数一的字符串传输出去后创建为文本文件,文本文件名由参数二决定,
1
dataList.Add(new MultipartFormFileSection("123123123123", "test.txt"));
-
字符串数据,编码格式,文件名(常用)
将参数一的字符串传输出去后创建为文本文件,文本文件编码格式由参数二决定,文本文件名由参数三决定
1
dataList.Add(new MultipartFormFileSection("123123123123", Encoding.UTF8, "test.txt"));
-
表单名,字节数组,文件名,文件类型
表单名是HTTP通信时使用的名字,参数二、三和传输文件二进制数据时使用的参数一致,参数四是资源类型,填法:ContentType的常用类型
1
dataList.Add(new MultipartFormFileSection("file", new byte[1024], "test.txt", "application/..."));
-
表单名,字符串数据,编码格式,文件名
表单名是HTTP通信时使用的名字,参数二、三、四和传输文本文件时使用的参数一致
1
dataList.Add(new MultipartFormFileSection("file", "123123123", Encoding.UTF8, "test.txt"));
-
上传相关API
-
Post
创建上传数据请求参数一是上传数据到哪个地址,参数二是上传的数据
Post
有多种重载,比较重要的是参数二的重载,对应了上传数据的各种形式参数二的上传数据可以传入一个字符串,一个 WWWFrom 对象,只有字符串消息字典形式的键值对消息,以及
List<IMultipartFormSection>
其中List<IMultipartFormSection>
类型的参数最为常用,因为它能将多个键值对消息和文件数据一起上传到服务端1
2
3
4
5
6
7
8
9List<IMultipartFormSection> data = new List<IMultipartFormSection>();
//键值对相关的消息数据
data.Add(new MultipartFormDataSection("Name", "MrTang"));
//添加二进制数据文件
data.Add(new MultipartFormFileSection("Test123.png", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png")));
//添加文本文件
data.Add(new MultipartFormFileSection("123123123", "Test123.txt"));
//使用Post方法创建上传请求
UnityWebRequest unityWebRequest = UnityWebRequest.Post("http://192.168.1.102/Http_Server/", data); -
Put
创建上传数据请求注意:
Put
请求类型不是所有的web服务器都认,它是HTTP/1.1的新请求,必须要服务器能够处理该请求类型那么才能有响应
Put
可以上传字符串形式和字节数据形式的数据,需要后端程序员配合处理1
2
3
4//读取某个文件的二进制数据
byte[] bytes = File.ReadAllBytes(Application.streamingAssetsPath + "/test.png");
//设置上传地址和上传内容
UnityWebRequest unityWebRequest = UnityWebRequest.Put("http://192.168.1.102/Http_Server/", bytes); -
当前上传的字节数
1
print($"上传字节数:{unityWebRequest.uploadedBytes}");
-
当前上传的进度(0~1)
1
print($"上传进度:{unityWebRequest.uploadProgress * 100}%");
Post发送操作
开启上传需要的协程后,我们先创建一个List<IMultipartFormSection>
的列表,便于我们一次将多个文件上传上去
然后就可以向列表添加键值对类型的数据MultipartFormDataSection
,添加文件数据MultipartFormDataSection
添加完毕后,通过UnityWebRequest.Post
传入要上传的地址和列表,创建一个UnityWebRequest
请求
我们可以直接yield return unityWebRequest.SendWebRequest()
以挂起协程等待上传结束,
也可以只执行unityWebRequest.SendWebRequest()
,然后每帧输出上传字节数和进度并挂起协程
上传结束后,我们通过unityWebRequest.result
来检测是否上传成功
值得一提的是,如果服务端的后端程序员配合,在上传完数据后会返回一个数据,
我们就可以通过unityWebRequest.downloadHandler.data
来获取它,相当于一起完成了上传与下载
1 | void Start() |
值得一提的是,这些IMultipartFormSection
派生出来的数据类,以及UnityWebRequest
上传的底层逻辑,
其实就有点类似于我们在使用Http上传数据时按照Http上传数据的规则所做的拼接工作,
上传多个数据类其实就是Unity底层帮助我们将这些类对象中的数据按照Http上传数据的规则拼接起来,再上传到服务器上
Put上传相关
注意:Put
请求类型不是所有的web服务器都认,它是HTTP/1.1的新请求,必须要服务器能够处理该请求类型那么才能有响应
Put
主要就是上传文件的请求,所以当服务器发现这是一个Put
类型的请求就会进行相对应的处理
它的实现逻辑相对Post
来说更加简单,但是同样需要后端程序员配合完成
1 | void Start() |