🛰️ UnityWebRequest 实践指南
🛰️ UnityWebRequest 实践指南
在 Unity 中进行网络通信,首选方案早已从 WWW 进化为 UnityWebRequest。它功能强大,支持 GET/POST/PUT/DELETE、文件上传/下载、JSON交互、证书校验、断点续传……一站式搞定。
🌐0.HTTP方法
| 方法 | 用途简述 | 是否携带数据 | 幂等性 | 典型用途示例 |
|---|---|---|---|---|
| GET | 获取数据 | ❌ 否 | ✅ 是 | 获取用户、商品详情 |
| POST | 新增资源 / 提交数据 | ✅ 是 | ❌ 否 | 创建订单、上传表单 |
| PUT | 更新整个资源 | ✅ 是 | ✅ 是 | 修改用户信息 |
| DELETE | 删除资源 | ❌/✅ 可选 | ✅ 是 | 删除用户、移除记录 |
Unity开发中使用场景
| 类型 | 示例 |
|---|---|
| GET | 拉配置 / 拉资源列表 / 请求状态 |
| POST | 登录 / 注册 / 提交反馈 / 创建记录 |
| PUT | 更新设置 / 修改用户信息 |
| DELETE | 删除角色 / 移除物品 / 清除缓存 |
🔹 1. 基础:GET 请求
xxxxxxxxxx
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
public class SimpleGet : MonoBehaviour
{
void Start()
{
StartCoroutine(GetData());
}
IEnumerator GetData()
{
UnityWebRequest req = UnityWebRequest.Get("https://jsonplaceholder.typicode.com/posts/1");
yield return req.SendWebRequest();
if (req.result == UnityWebRequest.Result.Success)
{
Debug.Log(req.downloadHandler.text);
}
else
{
Debug.LogError(req.error);
}
}
}
🔹 2. POST 请求(发送 JSON 数据)
xxxxxxxxxx
IEnumerator PostJson()
{
string json = JsonUtility.ToJson(new { username = "伯爵", score = 999 });
var request = new UnityWebRequest("https://example.com/api/post", "POST");
byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(json);
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
Debug.Log("Response: " + request.downloadHandler.text);
}
else
{
Debug.LogError("Error: " + request.error);
}
}
🌀 3. Modern 写法:async/await + UniTask(推荐)
用 UniTask 改写更现代,更易管理任务链和错误:
xxxxxxxxxx
using Cysharp.Threading.Tasks;
using UnityEngine.Networking;
public async UniTask<string> FetchAsync(string url)
{
using var request = UnityWebRequest.Get(url);
await request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
return request.downloadHandler.text;
else
throw new System.Exception($"网络失败: {request.error}");
}
调用方式:
xxxxxxxxxx
private async UniTaskVoid Start()
{
try
{
string content = await FetchAsync("https://api.github.com/users/unity3d");
Debug.Log("✅ Success: " + content);
}
catch (System.Exception ex)
{
Debug.LogError("❌ 网络错误: " + ex.Message);
}
}
⚠️ 4. 常见问题与陷阱
| 问题 | 原因 | 解决方案 |
|---|---|---|
request.error == "Unknown Error" |
HTTPS 请求失败 | 目标站未支持 TLS 或证书问题 |
| 中文乱码 | 编码问题 | Encoding.UTF8.GetString() 手动解码 |
CORS 跨域问题(WebGL) |
浏览器安全限制 | 需要服务器设置 Access-Control-Allow-Origin |
| Post Json 无响应 | 没加头 | 别忘了加 Content-Type: application/json |
🔐 5. 自定义请求头(Header)
xxxxxxxxxx
request.SetRequestHeader("Authorization", "Bearer xxx-token-abc");
request.SetRequestHeader("X-User-ID", "elegant-vampire");
🧪 6. Json 响应结构解析
xxxxxxxxxx
[System.Serializable]
public class User
{
public string name;
public int age;
}
User user = JsonUtility.FromJson<User>(json);
💡 Unity 内置
JsonUtility不支持复杂嵌套,如字典、数组对象。可使用Newtonsoft.Json或Utf8Json替代。
📥 7. 下载文件到本地磁盘
xxxxxxxxxx
IEnumerator DownloadFile(string url, string localPath)
{
UnityWebRequest request = UnityWebRequest.Get(url);
request.downloadHandler = new DownloadHandlerFile(localPath); // ✅ 直接写入磁盘
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
Debug.Log("文件保存至: " + localPath);
}
else
{
Debug.LogError("下载失败: " + request.error);
}
}
🌐 8. 实践场景总结
| 场景 | 推荐方式 |
|---|---|
| 查询接口数据 | UnityWebRequest.Get() + JsonUtility |
| 上传分数/状态 | UnityWebRequest.Post() + Json |
| 下载资源文件 | DownloadHandlerFile |
| WebGL 通信 | 需处理 CORS 和证书问题 |
| 请求队列管理 | 使用 UniTask + 自定义任务队列 |
9.断点续传示例
| 功能 | 实现方式 |
|---|---|
| 支持中断恢复 | 使用 UnityWebRequest + HTTP Range 请求 |
| 保存已下载数据 | 写入本地临时 .part 文件 |
| 合并为完整文件 | 下载完成后重命名为最终文件 |
xxxxxxxxxx
using System;
using System.IO;
using System.Threading;
using UnityEngine;
using UnityEngine.Networking;
using Cysharp.Threading.Tasks;
public class ResumeDownloader : MonoBehaviour
{
public string downloadUrl = "https://example.com/bigfile.zip";
public string savePath = "bigfile.zip";
private string TempPath => savePath + ".part";
public async UniTaskVoid StartDownload()
{
long existingSize = 0;
if (File.Exists(TempPath))
existingSize = new FileInfo(TempPath).Length;
using var request = UnityWebRequest.Get(downloadUrl);
request.SetRequestHeader("Range", $"bytes={existingSize}-");
string directory = Path.GetDirectoryName(savePath);
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
request.downloadHandler = new DownloadHandlerBuffer();
var op = request.SendWebRequest();
await UniTask.WaitUntil(() => op.isDone, cancellationToken: this.GetCancellationTokenOnDestroy());
if (request.result != UnityWebRequest.Result.Success && request.responseCode != 206 && request.responseCode != 200)
{
Debug.LogError($"❌ 下载失败: {request.error}");
return;
}
var data = request.downloadHandler.data;
// 追加写入到 .part 文件
using (var fs = new FileStream(TempPath, FileMode.Append, FileAccess.Write))
{
fs.Write(data, 0, data.Length);
}
Debug.Log($"✅ 下载分块成功,大小: {data.Length} 字节");
long totalSize = 0;
if (request.GetResponseHeader("Content-Range") is string range)
{
// Content-Range: bytes 1000-4999/12345
var totalMatch = System.Text.RegularExpressions.Regex.Match(range, @"/(\d+)");
if (totalMatch.Success)
totalSize = long.Parse(totalMatch.Groups[1].Value);
}
long currentSize = new FileInfo(TempPath).Length;
Debug.Log($"🧪 已下载: {currentSize} / {totalSize}");
if (currentSize >= totalSize)
{
File.Move(TempPath, savePath, true);
Debug.Log($"🎉 下载完成,文件保存在: {savePath}");
}
else
{
Debug.Log("⏸️ 下载未完成,可稍后继续");
}
}
[ContextMenu("断点续传下载测试")]
public void StartTest()
{
StartDownload().Forget();
}
}
✅ 面试题推荐(附解析)
- UnityWebRequest 与 WWW 的区别? → UnityWebRequest 是现代 API,支持更多功能、更安全,已取代 WWW。
- 如何判断 UnityWebRequest 请求成功? → 使用
request.result == UnityWebRequest.Result.Success(Unity 2020.1 起推荐) - 如何解决 WebGL 网络请求跨域失败? → 需要服务端设置 CORS 响应头,如
Access-Control-Allow-Origin: *。 - JsonUtility 无法解析复杂结构怎么办? → 使用
Newtonsoft.Json或System.Text.Json替代。 - async/await 和 Coroutine 区别? →
async/await结构清晰,可组合任务、异常处理好;Coroutine 更适合场景逻辑协程。
点赞鼓励下,(づ ̄3 ̄)づ╭❤~
作者:世纪末的魔术师
出处:https://www.cnblogs.com/Firepad-magic/
Unity最受欢迎插件推荐:点击查看
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号