🛰️ UnityWebRequest 实践指南
在 Unity 中进行网络通信,首选方案早已从 WWW 进化为 UnityWebRequest。它功能强大,支持 GET/POST/PUT/DELETE、文件上传/下载、JSON交互、证书校验、断点续传……一站式搞定。
🌐0.HTTP方法
🔹 1. 基础:GET 请求
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 数据)
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 改写更现代,更易管理任务链和错误:
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}");
}调用方式:
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. 常见问题与陷阱
🔐 5. 自定义请求头(Header)
request.SetRequestHeader("Authorization", "Bearer xxx-token-abc");
request.SetRequestHeader("X-User-ID", "elegant-vampire");🧪 6. Json 响应结构解析
[System.Serializable]
public class User
{
public string name;
public int age;
}
User user = JsonUtility.FromJson<User>(json);💡 Unity 内置
JsonUtility不支持复杂嵌套,如字典、数组对象。可使用Newtonsoft.Json或Utf8Json替代。
📥 7. 下载文件到本地磁盘
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. 实践场景总结
9.断点续传示例
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

评论
发表评论