一、前言

1. UnityWebRequest

官方描述:

UnityWebRequest 提供了一个模块化系统,用于构成 HTTP 请求和处理 HTTP 响应。UnityWebRequest 系统的主要目标是让 Unity 游戏与 Web 浏览器后端进行交互。该系统还支持高需求功能,例如分块 HTTP 请求、流式 POST/PUT 操作以及对 HTTP 标头和动词的完全控制。

从官方描述来看,对于UnityWebRequest类的升级更大程度代表了Unity对于Webgl网页浏览器支持的优化。

2.WWW类

其实5.4版本的时候就出了新的API UnityWebRequest用于替代WWW,有些较大的文件下载需要断点续传的功能(即下载了一部分突然中断下载后,再次下载直接从上次下载的地方继续下载,而不是重新下载)就需要使用HttpWebRequest或UnityWebRequest,在2017版本中WWW是还没有被弃用的,2018版本我没有试过,2019是已经被弃用的,使用的时候可以看到这个类被画上了绿色波浪。

这里大体的描述一下,后面还可能会持续深入解剖。下面讲述一下这个类的一些常用接口和使用

二、常用方法Get、Post、Put和Head

UnityWebRequest

架构:

UnityWebRequest 生态系统将 HTTP 事务分解为三个不同的操作:

  • 向服务器提供数据
  • 从服务器接收数据
  • HTTP 流量控制(例如,重定向和错误处理)

UnityWebRequest由三个元素组成:
1 UpLoadHandler处理数据将数据上传到服务器的对象;
2 DownLoadHandler从服务器下载数据的对象;
3 UnityWebRequest负责与HTTP通信并管理上面两个对象。还处理 HTTP 流量控制。此对象是定义自定义标头和 URL 的位置,也是存储错误和重定向信息的位置。

更多描述请看官网手册:https://docs.unity.cn/cn/2019.4/Manual/UnityWebRequest.html

 (1)常用方法:

方法 作用
SendWebRequest() 开始与远程服务器通信。在调用此方法之后,有必要的话UnityWebRequest将执行DNS解析,将HTTP请求发送到目标URL的远程服务器并处理服务器的响应。
Get(url) 创建一个HTTP为传入URL的UnityWebRequest对象
Post(url) 向Web服务器发送表单信息
Put(url) 将数据上传到Web服务器
Abort() 直接结束联网
Head() 创建一个为传输HTTP头请求的UnityWebRequest对象
GetResponseHeader() 返回一个字典,内容为在最新的HTTP响应中收到的所有响应头

(2)构造函数

public UnityWebRequest();
public UnityWebRequest(Uri uri);
public UnityWebRequest(Uri uri,string method);
public UnityWebRequest(Uri uri,string method,Networking.DownloadHandler downloadHandler, Networking.UploadHandler uploadHandler);
参数 含义
URL url网址信息或本地文件路径信息
method 相当于方法名,只有GET, POST, PUT, HEAD四种,默认为GET,一旦调用SendWebRequest(),就无法更改
downloadHandler 下载数据的委托方法
uploadHandler 上传数据的委托方法

下面介绍一下一些经常用的接口。介绍之前先简单聊聊GET、POST和PUT这三种方式的区别

1.Get:一般用于向服务器获取信息,举例:后台服务器有一个接口http://127.0.0.1/Get/?studentName=张三,这个接口负责返回学生名字为张三的数据,我们在提交get的时候,服务器会接收studentName下的值,通过这个值来进行逻辑处理,使用Get我们要访问得值是暴露在浏览器中的,如果是用户名密码这样的重要信息被暴露后果将不堪设想,所以像网页中搜索栏需要条件来获取信息的功能,就可以使用Get的方法来实现。

2.Post:这种方式就是为了解决Get访问时信息暴露的危险,使用Post访问时表单中的内容不会暴露,安全性更高,一般用于网页用户登录等重要信息上

3.Put:这种方式用于将数据发送到远程的服务器。比如文件上传。

1.Get方法

(1) 使用静态类创建UnityWebRequest获取Txt文本信息

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine.UI;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
using System;public class AAA : MonoBehaviour
{void Start(){StartCoroutine("GetDataB", "Test.txt");}#region 创建persistentDataPath文件夹IEnumerator GetDataB(string fileName){//1.url地址string fromPath = Application.streamingAssetsPath + "/" + fileName;//2.创建一个UnityWebRequest类 method属性为GetUnityWebRequest request = UnityWebRequest.Get(fromPath);//3.等待响应时间,超过5秒结束request.timeout = 5;//4.发送请求信息yield return request.SendWebRequest(); //5.判断是否下载完成if (request.isDone){//6.判断是否下载错误if (request.isHttpError || request.isNetworkError)Debug.Log(request.error);elseDebug.Log(request.downloadHandler.text);}}#endregion
}

(2) 使用构造来创建

注意:这里为什么要用两种方式呢?因为静态类创建(UnityWebRequest.Get)的Request是自带DownloadHandler和UploadHandler的,而构造创建(new UnityWebRequest )是没有的,需要自己手动创建赋值,注意不要踩坑哦!!

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine.UI;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
using System;public class AAA : MonoBehaviour
{void Start(){StartCoroutine("GetDataB", "Test.txt");}#region 创建persistentDataPath文件夹IEnumerator GetDataB(string fileName){string fromPath = Application.streamingAssetsPath + "/" + fileName;Uri uri = new Uri(fromPath);//UnityWebRequest request = UnityWebRequest.Get(fromPath);UnityWebRequest request =new UnityWebRequest(uri); //使用构造request.timeout = 5;//等待响应时间,超过5秒结束/*使用构造没有DownloadHandler和UploadHandler,所以要创建赋值,这里只用到了下载,所以可以不用创建UploadHandler* 下面罗列了三种不同类型的DownloadHandler1.DownloadHandlerBuffer 读取文件存储2.DownloadHandlerTexture 读取图片3.DownloadHandlerFile 下载文件到本地*/DownloadHandlerBuffer Download = new DownloadHandlerBuffer();request.downloadHandler = Download;yield return request.SendWebRequest();if (request.isDone){if (request.isHttpError || request.isNetworkError)Debug.Log(request.error);else Debug.Log(request.downloadHandler.text);}}#endregion}

2.Post方法

Post方法将一个表上传到远程的服务器,一般来说我们登陆某个网站的时候会用到这个方法,我们的账号密码会以一个表单的形式传过去。

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;/// <summary>
/// 网络请求测试
/// </summary>
public class ChinarWebRequest : MonoBehaviour
{void Start(){StartCoroutine(Post());}/// <summary>/// 开启一个协程,发送请求/// </summary>/// <returns></returns>IEnumerator Post(){WWWForm form = new WWWForm();//键值对form.AddField("key",  "value");form.AddField("name", "Chinar");//请求链接,并将form对象发送到远程服务器UnityWebRequest webRequest = UnityWebRequest.Post("http://www.baidu.com", form);yield return webRequest.SendWebRequest();if (webRequest.isHttpError || webRequest.isNetworkError){Debug.Log(webRequest.error);}else{Debug.Log("发送成功"); }}
}

3.Put方法

Put方法将数据发送到远程的服务器。例如:文件上传

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;/// <summary>
/// 网络请求测试
/// </summary>
public class ChinarWebRequest : MonoBehaviour
{void Start(){StartCoroutine(Upload());}/// <summary>/// 开启协程/// </summary>/// <returns></returns>IEnumerator Upload(){byte[] myData = System.Text.Encoding.UTF8.GetBytes("Chinar的测试数据");using (UnityWebRequest uwr = UnityWebRequest.Put("http://www.baidu.com", myData)){yield return uwr.SendWebRequest();if (uwr.isNetworkError || uwr.isHttpError){Debug.Log(uwr.error);}else{Debug.Log("上传成功!");}}}
}

4.Abort方法

Abort方法会尽快结束联网,可以随时调用此方法。
如果 UnityWebRequest尚未完成,那么 UnityWebRequest将尽快停止上传或下载数据。

中止的 UnityWebRequests被认为遇到了系统错误。isNetworkError或isHttpError属性将返回true,error属性将为“User Aborted”。

5.Head方法

Head方法与Get方法用法一致,都是传入一个URL。

关于head这个方法解释推荐文章:https://www.jianshu.com/p/49ebc4a78474

根据这个文章特点的截图 我简单聊聊Head作用 :

1.第一条就是只请求资源头部,网页的body主体是不显示的。大家可以先用get请求一个www.baidu.com查看

接下来我们使用Head来请求

 2.检查超链接有效性,当链接出现问题时会返回一个错误码,上方链接文章有对应错误码的中文描述。使用get、post也可以测试有效性,但是这些方式访问成功会返回body主体,所以使用head访问可以节省网络资源

3.网页是否被修改,举个例子,我们将一个静态网页使用MD5加密后存入数据库,在head中加入这个html被加密后的数据进行数据库访问判断,如果这个静态网页被修改访问就会出现问题。不过这是很久之前的版本用的方法,现在基本使用的时token进行验证

4.第四点就是头包含的这些信息了,例如我们需要获取安全验证信息来进心判断操作,如果使用GET、PUST等方式访问,就会连带body主体一起获取,大大浪费资源。

下面是UnityWebRequest.Head的请求方式:一般与下面的GetResponseHeader方法配合使用获取文件大小的,后面断电续传中会有用到。

    /// <summary>/// 开启一个协程,发送请求/// </summary>/// <returns></returns>IEnumerator SendRequest(){UnityWebRequest uwr = UnityWebRequest.Head("www.baidu.com");       //创建UnityWebRequest对象yield return uwr.SendWebRequest();                                 //等待返回请求的信息if (uwr.isHttpError || uwr.isNetworkError)                         //如果请求失败,或是 网络错误{Debug.Log(uwr.error); //打印错误原因}else //请求成功{Debug.Log("Head:请求成功");}}

6.GetResponseHeader方法

GetResponseHeader方法可以用来获取请求文件的长度 传入参数 "Content-Length"字符串,表示获取文件内容长度。

 IEnumerator SendRequest(){UnityWebRequest uwr = UnityWebRequest.Head("www.baidu.com"); //创建UnityWebRequest对象yield return uwr.SendWebRequest();                                 //等待返回请求的信息if (uwr.isHttpError || uwr.isNetworkError)                         //如果其 请求失败,或是 网络错误{Debug.Log(uwr.error); //打印错误原因}else //请求成功{long totalLength = long.Parse(uwr.GetResponseHeader("Content-Length")); //首先拿到文件的全部长度Debug.Log($"totalLength:{totalLength}" );//打印文件长度}}

三、常用属性

属性 类型 含义
timeout int 等待时间(秒)超过此数值是 UnityWebReqest的尝试连接将终止
isHttpError bool HTTP响应出现出现错误
isNetworkError bool 系统出现错误
error string 描述 UnityWebRequest对象在处理HTTP请求或响应时遇到的任何系统错误
downloadProgress float 表示从服务器下载数据的进度
uploadProgress float 表示从服务器上传数据的进度
isDone bool 是否完成与远程服务器的通信
SendWebRequest UnityWebRequestAsyncOperation 发送信息访问

四、案例

一、断点续传

记录已经下载到的本地文件大小,向资源服务器发送请求时,通过请求头实现拿到剩下需要下载的内容,然后接着下载
确保对同一个资源文件的下载操作,就不存在资源会下载错误的情况,如果你在断点续传的阶段发现资源服务器上的资源已经更新,那就得删除之前下载的文件然后重新下载。

using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;public class ChinarBreakpointRenewal : MonoBehaviour
{private bool _isStop;           //是否暂停public Slider ProgressBar;      //进度条public Text SliderValue;        //滑动条值public Button startBtn;        //开始按钮public Button pauseBtn;        //暂停按钮string Url = "https://downsc.chinaz.net/Files/DownLoad/sound1/201808/10447.wav";/// <summary>/// 初始化UI界面及给按钮绑定方法/// </summary>void Start(){//初始化进度条和文本框ProgressBar.value = 0;SliderValue.text = "0.0%";//开始、暂停按钮事件监听startBtn.onClick.AddListener(OnClickStartDownload);pauseBtn.onClick.AddListener(OnClickStop);}//开始下载按钮监听事件public void OnClickStartDownload(){//开启协程 *注意真机上要用Application.persistentDataPath路径*StartCoroutine(DownloadFile(Url, Application.streamingAssetsPath + "/MP4/test.mp4", CallBack));}/// <summary>/// 协程:下载文件/// </summary>/// <param name="url">请求的Web地址</param>/// <param name="filePath">文件保存路径</param>/// <param name="callBack">下载完成的回调函数</param>/// <returns></returns>IEnumerator DownloadFile(string url, string filePath, Action callBack){UnityWebRequest huwr = UnityWebRequest.Head(url); //使用Head方法可以获取到文件的全部长度yield return huwr.SendWebRequest();//发送信息请求//判断请求或系统是否出错if (huwr.isNetworkError || huwr.isHttpError) {Debug.Log(huwr.error); //出现错误 输出错误信息}else{long totalLength = long.Parse(huwr.GetResponseHeader("Content-Length")); //首先拿到文件的全部长度string dirPath = Path.GetDirectoryName(filePath);//获取文件的上一级目录if (!Directory.Exists(dirPath)) //判断路径是否存在{Directory.CreateDirectory(dirPath);//不存在创建}/*作用:创建一个文件流,指定路径为filePath,模式为打开或创建,访问为写入* 使用using(){}方法原因: 当同一个cs引用了不同的命名空间,但这些命名控件都包括了一个相同名字的类型的时候,可以使用using关键字来创建别名,这样会使代码更简洁。注意:并不是说两个名字重复,给其中一个用了别名,另外一个就不需要用别名了,如果两个都要使用,则两个都需要用using来定义别名的* using(类){} 括号中的类必须是继承了IDisposable接口才能使用否则报错* 这里没有出现不同命名空间出现相同名字的类属性可以不用using(){}*/using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write)){long nowFileLength = fs.Length; //当前文件长度,断点前已经下载的文件长度。Debug.Log(fs.Length);//判断当前文件是否小于要下载文件的长度,即文件是否下载完成if (nowFileLength < totalLength){Debug.Log("还没下载完成");/*使用Seek方法 可以随机读写文件* Seek()  ----------有两个参数 第一参数规定文件指针以字节为单位移动的距离。第二个参数规定开始计算的位置* 第二个参数SeekOrigin 有三个值:Begin  Current   End* fs.Seek(8,SeekOrigin.Begin);表示 将文件指针从开头位置移动到文件的第8个字节* fs.Seek(8,SeekOrigin.Current);表示 将文件指针从当前位置移动到文件的第8个字节* fs.Seek(8,SeekOrigin.End);表示 将文件指针从最后位置移动到文件的第8个字节*/fs.Seek(nowFileLength, SeekOrigin.Begin);  //从开头位置,移动到当前已下载的子节位置UnityWebRequest uwr = UnityWebRequest.Get(url); //创建UnityWebRequest对象,将Url传入uwr.SetRequestHeader("Range", "bytes=" + nowFileLength + "-" + totalLength);//修改请求头从n-m之间uwr.SendWebRequest();                      //开始请求if (uwr.isNetworkError || uwr.isHttpError) //如果出错{Debug.Log(uwr.error); //输出 错误信息}else{long index = 0;     //从该索引处继续下载while (nowFileLength < totalLength) //只要下载没有完成,一直执行此循环{if (_isStop) break;//如果停止跳出循环yield return null;byte[] data = uwr.downloadHandler.data;if (data != null){long length = data.Length - index;fs.Write(data, (int)index, (int)length); //写入文件index += length;nowFileLength += length;ProgressBar.value = (float)nowFileLength / totalLength;SliderValue.text = Math.Floor((float)nowFileLength / totalLength * 100) + "%";if (nowFileLength >= totalLength) //如果下载完成了{ProgressBar.value = 1; //改变Slider的值SliderValue.text = 100 + "%";/*这句话的作用是:如果callBack方法不为空则执行Invoke* 注意:* 1.这里的Invoke可不是Unity的Invoke延迟调用的用法,参考文章:https://blog.csdn.net/liujiejieliu1234/article/details/45312141 从文章中我们可以看到,C#中的Invoke是为了防止winform中子主线程刚开始创建对象时,子线程与主线程并发修改主线程尚未创建的对象属性。* 因为unity这里只有主线程没有用到子线程可以直接写callBack();*/callBack?.Invoke();break;}}}}}}}}/// <summary>/// 下载完成后的回调函数/// </summary>void CallBack(){Debug.Log("下载完成");}/// <summary>/// 暂停下载/// </summary>public void OnClickStop(){if (_isStop){pauseBtn.GetComponentInChildren<Text>().text = "暂停下载";Debug.Log("继续下载");_isStop = !_isStop;OnClickStartDownload();}else{pauseBtn.GetComponentInChildren<Text>().text = "继续下载";Debug.Log("暂停下载");_isStop = !_isStop;}}
}

如果以上有什么不对,或者可以优化的地方欢迎大家指正,感谢。

Unity之UnityWebRequest和使用相关推荐

  1. Unity 最新UnityWebRequest下载,同时显示下载进度,和 显示网速,今天贴出来和大家分享

    Unity 最新UnityWebRequest下载网络资源,支持断点续传.多文件同时下载,同时显示下载进度,和 显示网速,今天贴出来和大家分享 显示网速图片 附上案例链接 可下载 https://do ...

  2. Unity用UnityWebRequest和 BestHttp的GET和POST表单提交,与php交互

    目录 在unity2021中,WWW的资源加载方式过时了,新的方法为UnityWebRequest BestHttp的Get方式和Post方式 部分API 在unity2021中,WWW的资源加载方式 ...

  3. Unity使用UnityWebRequest实现本地日志上传到web服务器

    一.前言 Unity项目开发中,遇到bug的时候,我们一般是通过日志来定位问题,所以写日志到本地文件,或者把日志文件上传到web服务器这样的功能就很必要了.下面就介绍下如何实现日志写入本地文件和上传本 ...

  4. Unity通过UnityWebRequest进行Http链接

    文章目录 前言 一.Get和Post请求 二.设置头文件的Get请求和Post请求 三.数据转换 总结 前言 最近需要用Unity做一款链接HTTP服务器的游戏,因此对自己所做的东西进行记录,方便自己 ...

  5. Unity使用UnityWebRequest请求服务器json数据,webgl端服务器请求

    根据unity官方说的, WebGL 网络无法直接访问套接字 由于存在安全隐患,JavaScript 代码无法直接访问 IP 套接字来实现网络连接.因此,.NET 网络类(即 System.Net 命 ...

  6. Unity 使用UnityWebRequest问题小结

    UnityWebRequest是自带的下载资源的api,优点显而易见:封装好,简单用,兼容性跨平台非常好.缺点也显而易见:可拓展性差 下载小文件通常使用下面的方法: public IEnumerato ...

  7. unity 使用UnityWebRequest读取Json文件

    一.Json模板类 [Serializable] public class Settings {[SerializeField]public int Sleep;//等其他属性 } 二.读取 usin ...

  8. unity 轻型UnityWebRequest 加载

    项目内需要从web服加载texture,整理了一版简单的纹理管理,包含加载,卸载,控制同时加载数量 1.封装一个LoadingTexture,包含开始下载,中断,callback,释放,是否正在下载, ...

  9. Unity的Package了解(2020.3)

    unity 更新很快,很多package如果不及时了解,很容易造很多轮子或走很多弯路. 一.已验证包 ------------------------------------------------- ...

  10. Unity接入百度语音识别SDK windows平台

    1.先注册百度开放平台的账号,然后按文档申请试用资格及创建应用:https://ai.baidu.com/ai-doc/SPEECH/qknh9i8ed Windows平台选择"不需要&qu ...

最新文章

  1. R语言ggplot2可视化使用ggridges包可视化山脊图(Ridgeline Plots):山脊图(Ridgeline Plots)应用场景、受试者口服茶碱的之后观察茶碱的浓度变化的山脊图
  2. [SOJ] 简单哈希
  3. 新天龙八部服务器维护了吗,《新天龙八部》3月11日全服更新维护公告
  4. 数论六之计算几何——An Easy Problem,Ancient Berland Circus,Open-air shopping malls
  5. define定义的是什么类型_为什么Django 3后建议使用Field.choices枚举类型定义choices选项...
  6. Javascript实践-Function对象扩展之延时执行函数
  7. java beanshell_使用beanshell实现JAVA代码动态运行
  8. 惯性矩如何计算机械转动惯量,[转载]ug中的惯性矩与转动惯量
  9. 美团工作10个月心得
  10. 异数OS 织梦师-纤手(二)-- LPC RPC篇
  11. 【实验技术笔记】细胞表型检测之细胞周期(PI 染色)
  12. 基于蓝墨云班课的翻转课堂实践
  13. 学会自己测天气系列八卦基础 01
  14. Android - Bootloader? root原理?Recovery? SuperSU?Magisk?Xposed?ROM包?这都啥玩意?
  15. Python 批量下载SIGMOD,VLDB的论文 Mac OS
  16. 数据分析师有哪些等级
  17. Tushare社区验证Carhart四因子模型
  18. 数组练习题-java
  19. [darknet源码系列-3] 在darknet中,如何根据解析出来的配置进行网络层构建
  20. 怎么用 UDP 实现 TCP?

热门文章

  1. java标准化考试系统源码_java标准化考试系统
  2. 如何去掉空格 oracle,oracle数据库中如何去除空格
  3. Java二叉树的最大宽度详解版
  4. 沟通CTBS远程接入软件研究
  5. 本地搭建mysql数据库
  6. C++中10的N次方如何表示
  7. 解决360N4S骁龙版在国外使用碰到的问题,附详细root教程
  8. linux设备驱动之 i2c设备驱动 at24c08驱动程序分析【全部地址的操作】
  9. python数学实验与建模百度云_Python数学实验与建模
  10. HTTP利用API接口,解密生意参谋