当前位置: 首页 > web >正文

Unity UnityWebRequest高级操作

系列文章目录

unity知识点


文章目录

  • 系列文章目录
  • 前言
  • 一、使用 LLAPI —创建 UnityWebRequest
  • 二、创建 UploadHandler
  • 三、创建 DownloadHandler
    • 3-1、DownloadHandlerBuffer
    • 3-2、DownloadHandlerFile
    • 3-3、DownloadHandlerTexture
    • 3-4、DownloadHandlerAssetBundle
    • 3-5、DownloadHandlerAudioClip
    • 3-6、DownloadHandlerScript
    • 3-7、 避免垃圾收集开销
  • 四、壁纸分享
  • 五、总结


前言

HLAPI 旨在最大程度减少样板代码,而低级 API (LLAPI) 旨在实现最大的灵活性。通常,使用 LLAPI 会涉及到创建 UnityWebRequest,然后创建相应的 DownloadHandlers 或 UploadHandlers 并将它们附加到 UnityWebRequests。

本部分将详细介绍低级 API 中提供的选项以及目标用途:

  • 创建 UnityWebRequest
  • 创建 UploadHandler
  • 创建 DownloadHandler

请注意,HLAPI 和 LLAPI 并不互斥。如果需要调整某个常见方案,始终可以自定义通过 HLAPI 创建的 UnityWebRequest 对象。

博客将会介绍UnityWebRequest高级操作。希望这篇博客对Unity的开发者有所帮助。
大家好,我是心疼你的一切,不定时更新Unity开发技巧,觉得有用记得一键三连哦。
欢迎点赞评论哦.下面就让我们进入正文吧 。


提示:以下是本篇文章正文内容,下面案例可供参考

一、使用 LLAPI —创建 UnityWebRequest

与任何其他对象一样,WebRequest 也可以实例化。可使用两个构造函数:

  • 标准的无参数构造函数将创建一个所有设置均为空或默认值的新 UnityWebRequest。此函数中不会设置目标 URL,不会设置自定义标头,并且重定向限制设置为 32。
  • 第二个构造函数采用一个字符串参数。此构造函数将 UnityWebRequest 的目标 URL 分配给字符串参数的值,除此之外,与无参数的构造函数相同。

还可以设置多个其他属性,用于跟踪状态,以及检查 UnityWebRequest 的结果。

示例:

UnityWebRequest wr = new UnityWebRequest(); // 完全为空
UnityWebRequest wr2 = new UnityWebRequest("https://www.mysite.com"); // 设置目标 URL// 必须提供以下两项才能让 Web 请求正常工作
wr.url = "https://www.mysite.com";
wr.method = UnityWebRequest.kHttpVerbGET;   // 可设置为任何自定义方法,提供了公共常量wr.useHttpContinue = false;
wr.chunkedTransfer = false;
wr.redirectLimit = 0;  // 禁用重定向
wr.timeout = 60;       // 此设置不要太小,Web 请求需要一些时间

二、创建 UploadHandler

目前,仅一种类型的上传处理程序可用:UploadHandlerRaw。此类在构建时接受数据缓冲区。此缓冲区在内部复制到本机代码内存中,然后当远程服务器准备好接受主体数据时,此缓冲区由 UnityWebRequest 系统使用。

上传处理程序还接受“Content Type”字符串。如果在 UnityWebRequest 自身中没有设置 Content-Type 标头,则此字符串用于 UnityWebRequest 的 Content-Type 标头值。如果在 UnityWebRequest 对象上手动设置了 Content-Type 标头,则将忽略上传处理程序对象上的 Content-Type。

如果没有在 UnityWebRequest 或 UploadHandler 上设置 Content-Type,则系统会将 Content-Type 默认设置为 application/octet-stream。

UnityWebRequest 具有一个 disposeUploadHandlerOnDispose 属性,其默认值为 true。如果此属性为 true,则在处理 UnityWebRequest 对象时还将在附加的上传处理程序上调用 Dispose(),致使下载处理程序无用。如果保持对上传处理程序的引用时间长度超过对 UnityWebRequest 的引用时间长度,应将 disposeUploadHandlerOnDispose 设置为 false。
示例:

byte[] payload = new byte[1024];
// ... 使用数据填充有效负载 ...UnityWebRequest wr = new UnityWebRequest("https://www.mysite.com/data-upload");
UploadHandler uploader = new UploadHandlerRaw(payload);// 发送标头:"Content-Type: custom/content-type";
uploader.contentType = "custom/content-type";wr.uploadHandler = uploader;

三、创建 DownloadHandler

DownloadHandlers 有多种类型:

  • DownloadHandlerBuffer 用于简单的数据存储。
  • DownloadHandlerFile 用于下载文件并将文件保存到磁盘(内存占用少)。
  • DownloadHandlerTexture 用于下载图像。
  • DownloadHandlerAssetBundle 用于提取 AssetBundle。
  • DownloadHandlerAudioClip 用于下载音频文件。
  • DownloadHandlerMovieTexture 用于下载视频文件。由于 MovieTexture 已被弃用,因此建议您使用 VideoPlayer 进行视频下载和电影播放。
  • DownloadHandlerScript 是一个特殊类。就其本身而言,不会执行任何操作。但是,此类可由用户定义的类继承。此类接收来自 UnityWebRequest 系统的回调,然后可以使用这些回调在数据从网络到达时执行完全自定义的数据处理。
    这些 API 类似于 DownloadHandlerTexture 的接口。

UnityWebRequest 具有一个 disposeDownloadHandlerOnDispose 属性,其默认值为 true。如果此属性为 true,则在处理 UnityWebRequest 对象时还将在附加的下载处理程序上调用 Dispose(),致使下载处理程序无用。如果保持对下载处理程序的引用时间长度超过对 UnityWebRequest 的引用时间长度,应将 disposeDownloadHandlerOnDispose 设置为 false。

3-1、DownloadHandlerBuffer

此下载处理程序是最简单的,可处理大多数用例。它将接收的数据存储在本机代码缓冲区中。下载完成后,可使用字节数组或文本字符串的形式访问缓冲的数据。

示例:

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;public class MyBehaviour : MonoBehaviour {void Start() {StartCoroutine(GetText());}IEnumerator GetText() {UnityWebRequest www = new UnityWebRequest("https://www.my-server.com");www.downloadHandler = new DownloadHandlerBuffer();yield return www.SendWebRequest();if (www.result != UnityWebRequest.Result.Success) {Debug.Log(www.error);}else {// 以文本形式显示结果Debug.Log(www.downloadHandler.text);// 或者获取二进制数据形式的结果byte[] results = www.downloadHandler.data;}}
}

3-2、DownloadHandlerFile

这是大型文件的特殊下载处理程序。它将下载的字节直接写入文件,因此无论下载的文件大小如何,内存使用量都很低。与其他下载处理程序的区别在于,无法从此下载处理程序获取数据,所有数据都将保存到文件中。

示例:

using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;public class FileDownloader : MonoBehaviour {void Start () {StartCoroutine(DownloadFile());}IEnumerator DownloadFile() {var uwr = new UnityWebRequest("https://unity3d.com/", UnityWebRequest.kHttpVerbGET);string path = Path.Combine(Application.persistentDataPath, "unity3d.html");uwr.downloadHandler = new DownloadHandlerFile(path);yield return uwr.SendWebRequest();if (uwr.result != UnityWebRequest.Result.Success)Debug.LogError(uwr.error);elseDebug.Log("File successfully downloaded and saved to " + path);}
}

3-3、DownloadHandlerTexture

相较于使用 DownloadHandlerBuffer 下载图像文件,然后再使用 Texture.LoadImage 从原始字节创建纹理,使用 DownloadHandlerTexture 会更有效。

此下载处理程序将接收的数据存储在 UnityEngine.Texture中。在下载完成时,它将 JPEG 和 PNG 解码为有效的 UnityEngine.Texture objects。每个 DownloadHandlerTexture 对象只创建一个 UnityEngine.Texture 副本。这样会减少垃圾收集的性能问题。此处理程序在本机代码中执行缓冲、解压缩和纹理创建。另外,解压缩和纹理创建任务在工作程序线程上而不是主线程上执行,这样可以在加载大型纹理时改善帧时间。

最后,DownloadHandlerTexture 仅在最终创建纹理本身时分配托管内存,因此消除了与脚本中执行字节到纹理转换相关的垃圾收集开销。

示例:
以下示例从互联网下载 PNG 文件,将其转换为精灵,并将其分配给图像:

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;[RequireComponent(typeof(Image))]
public class ImageDownloader : MonoBehaviour {Image _img;void Start () {_img = GetComponent<UnityEngine.UI.Image>();Download("https://www.mysite.com/myimage.png");}public void Download(string url) {StartCoroutine(LoadFromWeb(url));}IEnumerator LoadFromWeb(string url){UnityWebRequest wr = new UnityWebRequest(url);DownloadHandlerTexture texDl = new DownloadHandlerTexture(true);wr.downloadHandler = texDl;yield return wr.SendWebRequest();if (wr.result == UnityWebRequest.Result.Success) {Texture2D t = texDl.texture;Sprite s = Sprite.Create(t, new Rect(0, 0, t.width, t.height),Vector2.zero, 1f);_img.sprite = s;}}
}

3-4、DownloadHandlerAssetBundle

这种专门的下载处理程序的优势在于能够将数据流式传输到 Unity 的 AssetBundle 系统。一旦 AssetBundle 系统收到足够的数据,AssetBundle 就可以作为 UnityEngine.AssetBundle 对象使用。仅会创建 UnityEngine.AssetBundle 对象的一个副本。因此大大减少了运行时内存分配以及加载 AssetBundle 带来的内存影响。此下载处理程序还允许在未完全下载的情况下部分使用 AssetBundle,因此可以流式传输资源。

所有下载和解压缩都在工作线程上进行。

AssetBundle 通过 DownloadHandlerAssetBundle 对象进行下载,该对象具有特殊的 assetBundle 属性可用于检索 AssetBundle。

由于 AssetBundle 系统的工作方式,所有 AssetBundle 都必须具有关联的地址。通常,该地址是它们所在的名义 URL(表示任何重定向之前的 URL)。在几乎任何情况下,都应该传入与传递给 UnityWebRequest 相同的 URL。使用高级 API (HLAPI) 时,此操作将自动完成。

示例:

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;public class MyBehaviour : MonoBehaviour {void Start() {StartCoroutine(GetAssetBundle());}IEnumerator GetAssetBundle() {UnityWebRequest www = new UnityWebRequest("https://www.my-server.com");DownloadHandlerAssetBundle handler = new DownloadHandlerAssetBundle(www.url, uint.MaxValue);www.downloadHandler = handler;yield return www.SendWebRequest();if (www.result != UnityWebRequest.Result.Success) {Debug.Log(www.error);}else {// 提取 AssetBundleAssetBundle bundle = handler.assetBundle;}}
}

3-5、DownloadHandlerAudioClip

此下载处理程序经过优化,用于下载音频文件。与使用 DownloadHandlerBuffer 来下载原始字节再从中创建 AudioClip 相比,此下载处理程序可以更方便地执行此操作。
示例:

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;public class AudioDownloader : MonoBehaviour {void Start () {StartCoroutine(GetAudioClip());}IEnumerator GetAudioClip() {using (var uwr = UnityWebRequestMultimedia.GetAudioClip("https://myserver.com/mysound.ogg", AudioType.OGGVORBIS)) {yield return uwr.SendWebRequest();if (uwr.result != UnityWebRequest.Result.Success) {Debug.LogError(uwr.error);yield break;}AudioClip clip = DownloadHandlerAudioClip.GetContent(uwr);// use audio clip}}
}

3-6、DownloadHandlerScript

对于需要完全控制下载数据处理的用户,Unity 提供了 DownloadHandlerScript 类。

默认情况下,此类的实例不执行任何操作。但是,如果您从 DownloadHandlerScript 派生自己的类,则可以重写某些函数并使用它们在数据从网络到达时接收回调。

注意:实际下载发生在工作线程上,但所有 DownloadHandlerScript 回调都在主线程上运行。应避免在这些回调期间执行计算量很大的操作。

要重写的函数
ReceiveContentLength()

protected void ReceiveContentLength(long contentLength);

收到 Content-Length 标头时调用此函数。请注意,如果服务器在处理 UnityWebRequest 的过程中发送一个或多个重定向响应,则此回调可能会多次发生。

OnContentComplete()

protected void OnContentComplete();

当 UnityWebRequest 完全从服务器下载所有数据并且已将所有接收的数据转发到 ReceiveData 回调时,将调用此函数。

ReceiveData()

protected bool ReceiveData(byte[] data, long dataLength);

数据从远程服务器到达后调用此函数,每帧调用一次。data 参数包含从远程服务器接收的原始字节,dataLength 表示数据数组中新数据的长度。

不使用预先分配的数据缓冲区的情况下,系统每次调用此回调时都会创建一个新的字节数组,而 dataLength 始终等于 data.Length。使用预分配的数据缓冲区的情况下,将重复使用数据缓冲区,并且必须使用 dataLength 来查找更新的字节数。

此函数需要返回值 true 或 false。如果返回 false,系统会立即中止 UnityWebRequest。如果返回 true,则处理将正常继续。

3-7、 避免垃圾收集开销

Unity 的许多高级用户都会关注如何减少因垃圾收集而导致的 CPU 峰值。对于这些用户,UnityWebRequest 系统允许预先分配托管代码字节数组,该数组用于将下载的数据传递给 DownloadHandlerScript 的 ReceiveData 回调。

使用此函数可以完全消除使用 DownloadHandlerScript 派生类捕获下载数据时的托管代码内存分配。

要让 DownloadHandlerScript 使用预先分配的托管缓冲区运行,请向 DownloadHandlerScript 的构造函数提供一个字节数组。

注意:字节数组的大小限制了每帧传递给 ReceiveData 回调的数据量。如果数据经过很多帧才缓慢到达,可能是因为提供的字节数组太小。

示例:

using UnityEngine;
using UnityEngine.Networking;public class LoggingDownloadHandler : DownloadHandlerScript {// 标准脚本化下载处理程序 - 在每个 ReceiveData 回调时分配内存public LoggingDownloadHandler(): base() {}// 预先分配的脚本化下载处理程序// 重用提供的字节数组来传递数据。// Eliminates memory allocation.public LoggingDownloadHandler(byte[] buffer): base(buffer) {}// 对于 DownloadHandler 基类而言是必需的。在处理 'bytes' 属性时调用。protected override byte[] GetData() { return null; }// 从网络收到数据后每帧调用一次。protected override bool ReceiveData(byte[] data, int dataLength) {if(data == null || data.Length < 1) {Debug.Log("LoggingDownloadHandler :: ReceiveData - received a null/empty buffer");return false;}Debug.Log(string.Format("LoggingDownloadHandler :: ReceiveData - received {0} bytes", dataLength));return true;}// 从服务器收到所有数据并通过 ReceiveData 传递后调用。protected override void CompleteContent() {Debug.Log("LoggingDownloadHandler :: CompleteContent - DOWNLOAD COMPLETE!");}// 从服务器收到 Content-Length 标头时调用。protected override void ReceiveContentLengthHeader(ulong contentLength) {Debug.Log(string.Format("LoggingDownloadHandler :: ReceiveContentLength - length {0}", contentLength));}
}

四、壁纸分享

在这里插入图片描述

五、总结

欲知后事如何,且听下回分解。
本次总结的就是这样的, 有需要会继续增加功能
如能帮助到你,就帮忙点个赞吧,三连更好哦,谢谢
你的点赞就是对博主的支持,有问题记得留言评论哦!
不定时更新Unity开发技巧,觉得有用记得一键三连哦。么么哒!

http://www.xdnf.cn/news/18588.html

相关文章:

  • Ubuntu部署K8S集群
  • Jmeter+Jenkins接口压力测试持续集成
  • 【motion】基于标签重合度的匹配算法1:原理
  • 3D打印小批量低成本打印玩具工艺品模型-中科米堆CASAIM
  • 字节Seed-OSS开源,不卷参数卷脑子
  • 从零开始搭 Linux 环境:VMware 下 CentOS 7 的安装与配置全流程(附图解)
  • 如何修复“DNS服务器未响应”错误
  • AP服务发现PRS_SOMEIPSD_00160的解析
  • 开源版CRM客户关系管理系统源码包+搭建部署教程
  • 深度学习入门详解:从神经网络到实践应用
  • vggt复现
  • 正点原子【第四期】Linux之驱动开发学习笔记-2.1LED灯驱动实验(直接操作寄存器)
  • Mysql InnoDB 底层架构设计、功能、原理、源码系列合集【四、事务引擎核心 - MVCC与锁机制】
  • 【AI应用】向量数据库Milvus详细命令
  • 找不到vcruntime140_1.dll 无法执行的故障要怎么搞?解决方法分享
  • MiniCPM-V4.0开源并上线魔乐社区,多模态能力进化,手机可用,还有最全CookBook!
  • CVPR焦点 | 神经网络新范式:轻量化与精度并行,重塑视觉任务性能天花板
  • 树状数组【原理+详解+例题】
  • 在Excel和WPS表格中如何隐藏单元格的公式
  • 改善收敛性有什么作用?收敛代表什么
  • 【Linux】Vim编辑器:从入门到高效使用
  • kafka生产者 消费者工作原理
  • golang 非error错误分类
  • 什么是短视频矩阵系统企业立项功能源码开发,支持OEM
  • 华为云物联网产品架构解析:资源空间、群组、产品、标签、网关、设备与子设备的关系梳理与设置指南
  • 【GPT入门】第54课 量化位数与存储大小的影响
  • 开发避坑指南(31):Oracle 11g LISTAGG函数使用陷阱,缺失WITHIN子句解决方案
  • Node.js中Express框架入门教程
  • PHY芯片的作用
  • C#_异步编程范式