文章目录
- 1 UnityWebRequest 介绍
- 2 搭建 HTTP 服务器
- 3 常用操作
- 3.1下载资源
- 3.1.1 下载文本
- 3.1.2 下载图片
- 3.1.3 下载 AB 包
- 3.2 上传资源
- 3.2.1 上传数据类
- 3.2.2 POST 上传
- 3.3.3 PUT 上传
- 4 自定义操作
- 4.1 下载资源
- 4.1.1 Unity 内置 Handler
- 4.1.2 自定义 Handler
- 4.2 上传资源
- 4.2.1 UploadHandlerRaw
- 4.2.2 UploadHandlerFile
本文环境
- Windows 11
- Unity 6000.0.42f1
1 UnityWebRequest 介绍
UnityWebRequest 是 Unity 提供的模块化的系统类,用于构成 HTTP 请求和处理 HTTP 响应。
它主要目标是让 Unity 游戏和 Web 服务端进行交互,将之前 WWW 的相关功能都集成在了其中,新版本中都建议使用 UnityWebRequest 类代替 WWW 类。
UnityWebRequest 在使用上和 WWW 很类似,主要区别是 UnityWebRequest 把下载下来的数据处理单独提取出来,可以根据自己的需求选择对应的数据处理对象来获取数据。
注意
- UnityWebRequest 和 WWW 一样,需要配合协同程序使用。
- UnityWebRequest 和 WWW 一样,支持 http、ftp、file 协议下载或加载资源。
- UnityWebRequest 能够上传文件到 HTTP 资源服务器。
常用操作
- 使用 Get 请求获取文本或二进制数据。
- 使用 Get 请求获取纹理数据。
- 使用 Get 请求获取 AB 包数据。
- 使用 Post 请求发送数据。
- 使用 Put 请求上传数据。
2 搭建 HTTP 服务器
- 搭建 HTTP 服务器过程参考:2025-05-11 Unity 网络基础10——HTTP通信-CSDN博客。
Unity 默认不允许不安全的连接(如 HTTP),如果服务器是本地开发服务器,可以启用 Unity 的 Allow downloads over HTTP
选项(位于 Edit > Project Settings > Player > Other Settings
)。

3 常用操作
3.1下载资源
3.1.1 下载文本
-
获取文本或二进制数据时
使用
UnityWebRequest.Get()
。
using UnityEngine;namespace Lesson
{using System.Collections;using UnityEngine.Networking;public class Lesson30 : MonoBehaviour{// 在Start方法中启动LoadText协程private void Start(){StartCoroutine(LoadText());}// 定义LoadText协程IEnumerator LoadText(){// 发送GET请求var req = UnityWebRequest.Get("http://你的 IP 地址:8000/HTTP Server/test.txt");// 等待请求完成yield return req.SendWebRequest();// 如果请求成功if (req.result == UnityWebRequest.Result.Success){// 打印下载的文本print(req.downloadHandler.text);// 获取下载的字节数组var bytes = req.downloadHandler.data;// 打印字节数组的长度print("字节数组长度: " + bytes.Length);}// 如果请求失败else{// 打印错误信息print($"获取失败: {req.error} | {req.result} | {req.responseCode}");}}}
}
将脚本挂载到 Unity 场景上并运行,得到以下结果。

3.1.2 下载图片
-
获取纹理图片数据时
使用
UnityWebRequestTexture.GetTexture()
,以及
DownloadHandlerTexture.GetContent()
。该方法也支持
- ftp 下载。
- file 本地文件下载。
using UnityEngine;namespace Lesson
{using System.Collections;using UnityEngine.Networking;using UnityEngine.UI;public class Lesson30 : MonoBehaviour{// 声明一个RawImage类型的变量Imgpublic RawImage Img;// 在Start方法中启动LoadText协程private void Start(){StartCoroutine(LoadTexture());}IEnumerator LoadTexture(){// 创建一个UnityWebRequestTexture对象,用于获取指定URL的纹理var req = UnityWebRequestTexture.GetTexture("http://你的 IP 地址:8000/HTTP Server/test.png");// var req = UnityWebRequestTexture.GetTexture("ftp://你的 IP 地址:8000/HTTP Server/test.png");// var req = UnityWebRequestTexture.GetTexture("file://" + Application.streamingAssetsPath + "/test.png");// 发送网络请求yield return req.SendWebRequest();// 如果请求成功if (req.result == UnityWebRequest.Result.Success){// 方法一// Img.texture = (req.downloadHandler as DownloadHandlerTexture).texture;// 方法二// 获取下载的纹理Img.texture = DownloadHandlerTexture.GetContent(req);}else{// 打印错误信息print($"获取失败: {req.error} | {req.result} | {req.responseCode}");}}}
}
将脚本挂载到 Unity 场景上,并在 Unity 场景中创建一个 RawImage 关联至 Img。
运行 Unity,RawImage 上出现了从服务器下载的图片。

3.1.3 下载 AB 包
-
获取 AB 包数据时
使用
UnityWebRequestAssetBundle.GetAssetBundle()
,以及
DownloadHandlerAssetBundle.GetContent()
。
using UnityEngine;namespace Lesson
{using System.Collections;using UnityEngine.Networking;using UnityEngine.UI;public class Lesson30 : MonoBehaviour{// 在Start方法中启动LoadText协程private void Start(){StartCoroutine(LoadAB());}IEnumerator LoadAB(){// 创建一个UnityWebRequest对象,用于获取AssetBundleUnityWebRequest req = UnityWebRequestAssetBundle.GetAssetBundle("http://你的 IP 地址:8000/HTTP Server/ab2");// 发送请求req.SendWebRequest();// 循环等待请求完成while (!req.isDone){// 打印下载进度print(req.downloadProgress);// 打印已下载的字节数print(req.downloadedBytes);// 等待一帧yield return null;}//yield return req.SendWebRequest();// 打印下载进度print(req.downloadProgress);// 打印已下载的字节数print(req.downloadedBytes);// 如果请求成功if (req.result == UnityWebRequest.Result.Success){// 获取AssetBundle对象// AssetBundle ab = (req.downloadHandler as DownloadHandlerAssetBundle).assetBundle;// 获取AssetBundle对象var ab = DownloadHandlerAssetBundle.GetContent(req);// 打印AssetBundle的名称print(ab.name);}else{// 打印错误信息print($"获取失败: {req.error} | {req.result} | {req.responseCode}");}}}
}
3.2 上传资源
3.2.1 上传数据类
父接口:IMultipartFormSection
- 所有上传数据类的父接口
- 可以使用父类容器存储子类对象
var dataList = new List<IMultipartFormSection>();
子类1:MultipartFormDataSection
- 用于上传普通数据
// 1. 二进制字节数组
dataList.Add(new MultipartFormDataSection(Encoding.UTF8.GetBytes("123123123123123")));// 2. 字符串
dataList.Add(new MultipartFormDataSection("12312312312312312dsfasdf"));// 3. 带参数名和编码类型(常用)
dataList.Add(new MultipartFormDataSection("Name", "xxx", Encoding.UTF8, "application/...."));// 4. 带参数名的字节数组
dataList.Add(new MultipartFormDataSection("Msg", new byte[1024], "appl....."));
子类2:MultipartFormFileSection
- 用于上传文件数据
// 1. 简单字节数组
dataList.Add(new MultipartFormFileSection(File.ReadAllBytes(Application.streamingAssetsPath + "/test.png")));// 2. 带文件名的字节数组(常用)
dataList.Add(new MultipartFormFileSection("上传的文件.png", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png")));// 3. 字符串数据+文件名(常用)
dataList.Add(new MultipartFormFileSection("12312313212312", "test.txt"));// 4. 带编码格式的字符串数据+文件名(常用)
dataList.Add(new MultipartFormFileSection("12312313212312", Encoding.UTF8, "test.txt"));// 5. 完整参数:表单名+字节数组+文件名+文件类型
dataList.Add(new MultipartFormFileSection("file", new byte[1024], "test.txt", ""));// 6. 完整参数:表单名+字符串数据+编码格式+文件名
dataList.Add(new MultipartFormFileSection("file", "123123123", Encoding.UTF8, "test.txt"));
3.2.2 POST 上传
基本流程
- 准备上传数据列表。
- 创建
UnityWebRequest.POST
请求。 - 发送请求并监控进度。
- 处理响应结果。
using UnityEngine;namespace Lesson
{using System;using System.Collections;using System.Collections.Generic;using System.IO;using UnityEngine.Networking;using UnityEngine.UI;public class Lesson31 : MonoBehaviour{// 在Start方法中启动LoadText协程private void Start(){StartCoroutine(Upload());}IEnumerator Upload(){// 创建一个包含要上传的数据的列表var data = new List<IMultipartFormSection>{// 添加一个名为Name的表单字段,值为xxxnew MultipartFormDataSection("Name", "xxx"),// 添加一个名为png的文件字段,值为test.png文件的内容new MultipartFormFileSection("png", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png")),// 添加一个名为txt的文本字段,值为12312321231232123new MultipartFormFileSection("txt", "12312321231232123"),};// 创建一个POST请求,将数据发送到指定的URLvar req = UnityWebRequest.Post("http://你的 IP 地址:8000/HTTP Server/", data);// 发送请求req.SendWebRequest();// 循环等待请求完成while (!req.isDone){// 打印上传进度print(req.uploadProgress);// 打印已上传的字节数print(req.uploadedBytes);// 等待一帧yield return null;}// 打印上传进度print(req.uploadProgress);// 打印已上传的字节数print(req.uploadedBytes);// 如果请求成功if (req.result == UnityWebRequest.Result.Success){// 打印上传成功print("上传成功");// req.downloadHandler.data}else{// 打印获取失败的信息print($"获取失败: {req.error} | {req.result} | {req.responseCode}");}}}
}
将脚本挂载到 Unity 场景上并运行,得到以下结果。

在服务器文件夹中,可看到上传了 2 个文件(注意要确认可以匿名访问服务器,才可上传成功)。

3.3.3 PUT 上传
- 不是所有服务器都支持 PUT 方法。
- 需要服务器端明确支持 PUT 请求处理。
IEnumerator UploadPut()
{var req = UnityWebRequest.Put("http://你的 IP 地址:8000/HTTP Server/", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png"));yield return req.SendWebRequest();if (req.result == UnityWebRequest.Result.Success){print("Put 上传成功");}else{ }
}
4 自定义操作
自定义作指使用 UnityWebRequest 提供的底层功能来处理常规封装方法无法满足的需求,核心思想是将数据处理与网络传输分离。通过自定义 DownloadHandler 和 UploadHandler,实现更灵活的数据获取和上传功能。
相关 API
// 1.构造函数
UnityWebRequest req = new UnityWebRequest();// 2.请求地址
req.url = "服务器地址";// 3.请求类型
req.method = UnityWebRequest.kHttpVerbPOST;// 4.进度
req.downloadProgress
req.uploadProgress// 5.超时设置
req.timeout = 2000;// 6.上传、下载的字节数
req.downloadedBytes
req.uploadedBytes// 7.重定向次数 设置为0表示不进行重定向 可以设置次数
req.redirectLimit = 10;// 8.状态码、结果、错误内容
req.result
req.error
req.responseCode// 9.下载、上传处理对象
req.downloadHandler
req.uploadHandler
4.1 下载资源
4.1.1 Unity 内置 Handler
处理器类型 | 用途 | 示例 | 获取数据方式 | 特点 |
---|---|---|---|---|
DownloadHandlerBuffer | 原始二进制数据 | new DownloadHandlerBuffer() | handler.data | 最基础的处理方式 |
DownloadHandlerFile | 直接保存到文件 | new DownloadHandlerFile(path) | 自动保存到指定路径 | 内存占用少,适合大文件 |
DownloadHandlerTexture | 图片下载 | new DownloadHandlerTexture() | handler.texture | 自动转换为 Texture2D |
DownloadHandlerAssetBundle | AB 包下载 | new DownloadHandlerAssetBundle(url, crc) | handler.assetBundle | 支持 CRC 校验 |
DownloadHandlerAudioClip | 音频下载 | UnityWebRequestMultimedia.GetAudioClip() | DownloadHandlerAudioClip.GetContent(req) | 需要指定音频类型 |
DownloadHandler 的使用基本遵循以下模式:
- 创建 UnityWebRequest 对象:指定 URL 和请求方法。
- 创建特定类型的 DownloadHandler:根据要下载的数据类型选择。
- 将 DownloadHandler 赋给请求对象:
req.downloadHandler = handler
。 - 发送请求:
yield return req.SendWebRequest()
。 - 处理结果:检查
req.result
,成功后通过 handler 获取数据。
DownLoadTexture 示例
IEnumerator DownLoadTexture()
{// 创建一个UnityWebRequest对象,用于发送HTTP请求var req = new UnityWebRequest("http://你的 IP 地址:8000/Http Server/test.png",UnityWebRequest.kHttpVerbGET);// 创建一个DownloadHandlerTexture对象,用于处理下载的纹理var textureHandler = new DownloadHandlerTexture();// 将DownloadHandlerTexture对象赋值给UnityWebRequest对象的downloadHandler属性req.downloadHandler = textureHandler;// 发送HTTP请求yield return req.SendWebRequest();// 如果请求成功if (req.result == UnityWebRequest.Result.Success){// 将下载的纹理赋值给Image对象的texture属性Image.texture = textureHandler.texture;}else{// 打印错误信息print("获取数据失败" + req.result + req.error + req.responseCode);}
}
DownLoadAB 示例
IEnumerator DownLoadAB()
{// 创建一个UnityWebRequest对象,用于发送HTTP请求var req = new UnityWebRequest("http://你的 IP 地址:8000/Http Server/ab", UnityWebRequest.kHttpVerbGET);// 创建一个DownloadHandlerAssetBundle对象,用于处理下载的AssetBundle// 第二个参数需要已知校检码才能进行比较,检查完整性。如果不知道的话只能传0,不进行完整性的检查// 所以一般只有进行AB包热更新时,服务器发送对应的文件列表中包含了验证码才能进行检查var handler = new DownloadHandlerAssetBundle(req.url, 0);// 将DownloadHandlerAssetBundle对象赋值给UnityWebRequest对象的downloadHandler属性req.downloadHandler = handler;// 发送HTTP请求yield return req.SendWebRequest();// 如果请求成功if (req.result == UnityWebRequest.Result.Success){// 获取下载的AssetBundlevar ab = handler.assetBundle;// 打印AssetBundle的名称print(ab.name);}// 如果请求失败else{// 打印错误信息print("获取数据失败" + req.result + req.error + req.responseCode);}
}
DownLoadAudioClip 示例
IEnumerator DownLoadAudioClip()
{// 创建一个UnityWebRequestMultimedia对象,用于获取音频文件var req = UnityWebRequestMultimedia.GetAudioClip("http://你的 IP 地址:8000/Http Server/Night Changes.mp3", AudioType.MPEG);// 发送网络请求yield return req.SendWebRequest();// 如果请求成功if (req.result == UnityWebRequest.Result.Success){// 获取音频文件内容var a = DownloadHandlerAudioClip.GetContent(req);}// 如果请求失败else{// 打印错误信息print("获取数据失败" + req.result + req.error + req.responseCode);}
}
DownLoadAudioClip 中,由于创建时不是
new UnityWebRequest()
,而是指定了特殊的创建方法。因此不设置DownloadHandlerAudioClip
,而是通过DownloadHandlerAudioClip
获得音频文件。
4.1.2 自定义 Handler
以上这些类是 Unity 中实现的用于解析下载下来的数据的类,使用对应的类处理下载数据,他们就会在内部将下载的数据处理为对应的类型。
DownloadHandlerScript
是一个特殊类,本身而言不会执行任何操作。但此类可由用户定义的类继承,接收来自 UnityWebRequest 系统的回调,然后使用这些回调在数据从网络到达时执行完全自定义的数据处理。
自定义下载器
public class CustomDownLoadFileHandler : DownloadHandlerScript
{// 用于保存本地存储时的路径private string _savePath;// 用于缓存收到的数据的容器private byte[] _cacheBytes;// 这是当前已收到的数据长度private int _index = 0;public CustomDownLoadFileHandler() : base(){ }public CustomDownLoadFileHandler(byte[] bytes) : base(bytes){ }public CustomDownLoadFileHandler(string path) : base(){_savePath = path;}protected override byte[] GetData(){// 返回字节数组return _cacheBytes;}/// <summary>/// 从网络收到数据后,每帧会自动调用的方法/// </summary>protected override bool ReceiveData(byte[] data, int dataLength){Debug.Log("收到数据长度:" + data.Length);Debug.Log("收到数据长度dataLength:" + dataLength);data.CopyTo(_cacheBytes, _index);_index += dataLength;return true;}/// <summary>/// 从服务器收到 Content-Length标头时,会自动调用的方法/// </summary>protected override void ReceiveContentLengthHeader(ulong contentLength){// base.ReceiveContentLengthHeader(contentLength);Debug.Log("收到数据长度:" + contentLength);// 根据收到的标头,决定字节数组容器的大小_cacheBytes = new byte[contentLength];}/// <summary>/// 当消息收完了会自动调用的方法/// </summary>protected override void CompleteContent(){Debug.Log("消息收完");// 把收到的字节数组进行自定义处理,我们在这处理成存储到本地File.WriteAllBytes(_savePath, _cacheBytes);}
}
使用自定义下载器
using UnityEngine;namespace Lesson
{using System.Collections;using System.IO;using UnityEngine.Networking;using UnityEngine.UI;public class Lesson32 : MonoBehaviour{// 在Start方法中启动LoadText协程private void Start(){StartCoroutine(DownLoadCustomHandler());}IEnumerator DownLoadCustomHandler(){// 创建一个UnityWebRequest对象,用于发送HTTP请求var req = new UnityWebRequest("http://你的 IP 地址:8000/Http Server/Night Changes.mp3", UnityWebRequest.kHttpVerbGET);// 使用自定义的下载处理对象来处理获取到的2进制字节数组req.downloadHandler = new CustomDownLoadFileHandler(Application.streamingAssetsPath + "/Night Changes.mp3");// 发送HTTP请求yield return req.SendWebRequest();// 判断请求是否成功if (req.result == UnityWebRequest.Result.Success){// 打印成功信息print("存储本地成功");}else{// 打印失败信息print("获取数据失败" + req.result + req.error + req.responseCode);}}public class CustomDownLoadFileHandler : DownloadHandlerScript{...}}
}
4.2 上传资源
UnityWebRequest 类的常用操作中,上传数据相关内容已经封装的很好了,可以很方便的上传参数和文件,因此使用常用操作已经能够满足常用需求,以下内容主要做了解。
UnityWebRequest 提供了两种主要的上传数据处理方式:
UploadHandlerRaw
- 用于上传字节数组数据。UploadHandlerFile
- 用于上传文件数据。
这些上传处理器会自动处理数据转换和传输过程,只需提供原始数据即可。
4.2.1 UploadHandlerRaw
- 功能:上传原始字节数组数据。
- 特点
- 适合上传结构化数据如 JSON、XML 等。
- 需要手动设置 contentType。
- 数据会被复制到 native 内存中。
IEnumerator UpLoadRaw()
{// 创建一个UnityWebRequest对象,指定请求的URL和请求方法var req = new UnityWebRequest("http://你的 IP 地址:8000/Http Server/", UnityWebRequest.kHttpVerbPOST);// 将字符串转换为字节数组byte[] bytes = Encoding.UTF8.GetBytes("123123123123123");// 设置上传处理程序,将字节数组作为上传数据req.uploadHandler = new UploadHandlerRaw(bytes);// 设置上传处理程序的Content-Type为application/octet-streamreq.uploadHandler.contentType = "application/octet-stream";// 发送请求,并等待响应yield return req.SendWebRequest();// 打印请求结果print(req.result);
}
4.2.2 UploadHandlerFile
- 功能:直接上传文件内容。
- 特点:
- 适合上传大文件,内存占用低。
- 文件会分块读取和上传。
- 默认 contentType 为
application/octet-stream
。
IEnumerator UpLoadFile()
{// 创建一个UnityWebRequest对象,指定请求的URL和请求方法var req = new UnityWebRequest("http://你的 IP 地址:8000/Http Server/", UnityWebRequest.kHttpVerbPOST);// 设置上传文件的路径req.uploadHandler = new UploadHandlerFile(Application.streamingAssetsPath + "/test.png");// 发送请求并等待响应yield return req.SendWebRequest();// 打印请求结果print(req.result);
}
UploadHandler 会自动处理 contentType,优先级如下:
- 如果在 UnityWebRequest 上手动设置了 Content-Type 头,则使用该值。
- 如果在 UploadHandler 上设置了 contentType,则使用该值。
- 默认使用
application/octet-stream
。
常见 contentType 值
application/json
- JSON数据application/xml
- XML数据image/png
- PNG图片application/octet-stream
- 二进制流(默认)
注意事项
UnityWebRequest 默认会在 Dispose 时自动释放 uploadHandler。
如果需要保留 uploadHandler 引用,需设置
req.disposeUploadHandlerOnDispose = false;
使用 using 语句确保资源释放。
using(UnityWebRequest req = new UnityWebRequest(...)) {// 使用请求 }