Unity的HTTP请求类相关代码如下:
在Unity的Project窗口下创建如下文件夹及对应脚本

HttpDriver类的相关代码如下所示:
cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
/// <summary>
/// HTTP请求驱动类(协程实现)
/// </summary>
public class HttpDriver : MonoBehaviour
{
// 单例模式(可选)
private static HttpDriver _instance;
public static HttpDriver Instance
{
get
{
if (_instance == null)
{
var obj = new GameObject("HttpDriver");
_instance = obj.AddComponent<HttpDriver>();
DontDestroyOnLoad(obj);
}
return _instance;
}
}
/// <summary>
/// 发送HTTP请求
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="type">请求类型</param>
/// <param name="onSuccess">成功回调</param>
/// <param name="onError">失败回调</param>
/// <param name="bodyData">POST/PUT请求体(JSON字符串)</param>
/// <param name="headers">请求头</param>
/// <param name="timeout">超时时间(秒)</param>
public void SendRequest(
string url,
HttpRequestType type,
Action<string> onSuccess,
Action<string> onError,
string bodyData = null,
Dictionary<string, string> headers = null,
int timeout = 10
)
{
StartCoroutine(ExecuteRequest(url, type, onSuccess, onError, bodyData, headers, timeout));
}
private IEnumerator ExecuteRequest(
string url,
HttpRequestType type,
Action<string> onSuccess,
Action<string> onError,
string bodyData,
Dictionary<string, string> headers,
int timeout
)
{
// 记录请求开始时间
float startTime = Time.realtimeSinceStartup;
UnityWebRequest request = CreateRequest(url, type, bodyData, headers, timeout);
if (request == null) // 增加空请求检查
{
onError?.Invoke("Failed to create request");
yield break;
}
yield return request.SendWebRequest();
// 计算耗时(毫秒)
float elapsedTime = (Time.realtimeSinceStartup - startTime) * 1000f;
if (request.result == UnityWebRequest.Result.Success)
{
// 构建详细日志信息
string logInfo = BuildSuccessLog(
url: url,
method: type.ToString(),
requestData: bodyData,
response: request.downloadHandler.text,
elapsedTime: elapsedTime,
headers: headers
);
Debug.Log(logInfo);
onSuccess?.Invoke(request.downloadHandler.text);
}
else
{
string errorLog = BuildErrorLog(
url: url,
method: type.ToString(),
error: request.error,
response: request.downloadHandler.text,
elapsedTime: elapsedTime
);
Debug.LogError(errorLog);
onError?.Invoke($"Error: {request.error}\nResponse: {request.downloadHandler.text}");
}
request.Dispose();
}
/// <summary>
/// 构建成功请求的日志信息
/// </summary>
private string BuildSuccessLog(
string url,
string method,
string requestData,
string response,
float elapsedTime,
Dictionary<string, string> headers)
{
return $"\n========== HTTP请求成功 ==========\n" +
$"URL地址: {url}\n" +
$"请求类型: {method}\n" +
$"请求头: {(headers != null ? string.Join(", ", headers) : "无")}\n" +
$"请求数据: {(string.IsNullOrEmpty(requestData) ? "无" : requestData)}\n" +
$"消耗时间: {elapsedTime:F2}ms\n" +
$"服务器返回: {response}\n" +
$"=================================\n";
}
/// <summary>
/// 构建错误请求的日志信息
/// </summary>
private string BuildErrorLog(
string url,
string method,
string error,
string response,
float elapsedTime)
{
return $"\n========== HTTP请求失败 ==========\n" +
$"URL地址: {url}\n" +
$"请求类型: {method}\n" +
$"错误信息: {error}\n" +
$"消耗时间: {elapsedTime:F2}ms\n" +
$"服务器返回: {response}\n" +
$"=================================\n";
}
private UnityWebRequest CreateRequest(
string url,
HttpRequestType type,
string bodyData,
Dictionary<string, string> headers,
int timeout
)
{
UnityWebRequest request = null;
try
{
// 强制初始化关键对象
request = new UnityWebRequest(url, type.ToString())
{
downloadHandler = new DownloadHandlerBuffer(),
timeout = timeout
};
// 处理POST/PUT请求体(增加空检查)
if (type == HttpRequestType.POST || type == HttpRequestType.PUT)
{
request.uploadHandler = new UploadHandlerRaw(
string.IsNullOrEmpty(bodyData)
? System.Text.Encoding.UTF8.GetBytes("{}")
: System.Text.Encoding.UTF8.GetBytes(bodyData)
);
}
// 安全添加请求头
if (headers != null)
{
foreach (var header in headers)
{
if (!string.IsNullOrEmpty(header.Value))
request.SetRequestHeader(header.Key, header.Value);
}
}
}
catch (System.Exception e)
{
Debug.LogError($"CreateRequest failed: {e.Message}");
request?.Dispose();
return null;
}
return request;
}
}
HttpUtility的相关代码如下所示:
cs
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
/// <summary>
/// HTTP工具类(静态方法)
/// </summary>
public static class HttpUtility
{
/// <summary>
/// 将字典转换为URL查询字符串
/// </summary>
public static string ToQueryString(Dictionary<string, string> parameters)
{
if (parameters == null || parameters.Count == 0)
return "";
var query = new System.Text.StringBuilder();
foreach (var pair in parameters)
{
query.Append($"{UnityWebRequest.EscapeURL(pair.Key)}={UnityWebRequest.EscapeURL(pair.Value)}&");
}
return query.ToString().TrimEnd('&');
}
/// <summary>
/// 生成带参数的完整URL
/// </summary>
public static string BuildUrl(string baseUrl, Dictionary<string, string> parameters)
{
if (parameters == null || parameters.Count == 0)
return baseUrl;
return $"{baseUrl}?{ToQueryString(parameters)}";
}
}
HttpRequestType的相关代码如下:
cs
/// <summary>
/// HTTP请求类型枚举
/// </summary>
public enum HttpRequestType
{
GET,
POST,
PUT,
DELETE,
PATCH
}
编写TestRequest脚本调用进行请求测试,以百度贴吧为例:
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestRequest : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
if (HttpDriver.Instance != null)
{
// 发送GET请求
HttpDriver.Instance.SendRequest(
url: "https://www.baidu.com",
type: HttpRequestType.GET,
onSuccess: (response) => {
Debug.Log("处理成功响应: " + response);
},
onError: (error) => {
Debug.LogError("处理错误: " + error);
}
);
}
}
}
在Unity中运行结果如下所示:

接入接口
登录接口
URL:http://www.example.com/user/Login(举例,非真实网址)
请求类型:POST
服务器:www.example.com
服务:HTTP
参数
Phone=xxx(注册的手机号)
Email=xxx(注册的邮箱)
Password=xxx(注册密码)
返回值
Code:服务器状态号
Data:登录返回数据
注册接口
URL:http://www.example.com/user/Register(举例,非真实网址)
请求类型:POST
服务器:www.example.com
服务:HTTP
参数
Phone=xxx(注册的手机号)
Email=xxx(注册的邮箱)
Password=xxx(注册密码)
服务器状态号(据具体服务器情况)
相关代码如下:(其余代码不做变动)
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIRegisterController : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
// 发送POST请求
var postData = "{" +
"\"email\":\"[email protected]\", " +
"\"password\":\"12345678901\"" + // 注意添加逗号
//"\"password\":\"123890\", " + // 注意添加逗号
//"\"VerifyCode\":\"123890\"" +
"}";
HttpDriver.Instance.SendRequest(
url: "https://reqres.in/api/register", // 修正URL
type: HttpRequestType.POST,
onSuccess: (response) => {
Debug.Log($"注册成功:{response}");
},
onError: (error) => {
Debug.LogError($"注册失败:{error}");
},
headers: new Dictionary<string, string> {
{"Content-Type", "application/json"},
{"User-Agent", "Mozilla/5.0"},
{"x-api-key", "reqres-free-v1"} // Added API key header
},
bodyData: postData
);
}
// Update is called once per frame
void Update()
{
}
}

下图在上图代码的基础上修改了URL值,地址见图: 制作简易UI实现UI登录注册请求:
UIRegisterController脚本添加同UILoginController脚本相同的CloseClick方法
其余脚本如下:
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UILoginController : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
public void CloseClick()
{
Destroy(gameObject);
}
}
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIAccoutController : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
public void LoginClick()
{
Prefabs.Load("WebPrefabs/UI/Login");
}
public void RegisterClick()
{
Prefabs.Load("WebPrefabs/UI/Register");
}
}
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public static class Prefabs
{
// 根据预制体路径,加载UI页面
public static GameObject Load(string path)
{
// 加载预制体
// 资源第一次加载后,会产生缓存,所以后面的加载会变快
Object prefab = Resources.Load(path);
// 实例化预制体
GameObject page = Object.Instantiate(prefab) as GameObject;
// 将页面放在Canvas下
page.transform.SetParent(GameObject.Find("/Canvas").transform);
page.transform.localPosition = Vector3.zero;
page.transform.localRotation = Quaternion.identity;
page.transform.localScale = Vector3.one;
// 四锚点边距归零
RectTransform rt = page.transform as RectTransform;
rt.offsetMin = Vector2.zero;
rt.offsetMax = Vector2.zero;
// 去掉初始化的Clone后缀
page.name = prefab.name;
return page;
}
}
模拟注册界面:

分别测试不同输入框是否实现代码,测试结果如下(此为不同测试汇总):

UIRegisterController脚本中变动如下:
cs
}
public void RegisterClick()
{
//Debug.Log(email.text);
//邮箱填写
if (email.text == "")
{
Debug.Log("需要填写邮箱");
return;
}
//两次密码都填写
if (password.text == "" || rPassword.text == "")
{
Debug.Log("两次密码必须都填写");
return;
}
//两次密码一致
if(password.text!=rPassword.text)
{
Debug.Log("两次密码必须一致");
return;
}
//请求服务器
// 发送POST请求
var postData = "{" +
"\"email\":\"" +email.text +"\","+
"\"password\":\""+password.text + "\""+ // 注意添加逗号
//"\"rPassword\":\"+rPassword.text+\" " + // 注意添加逗号
//"\"VerifyCode\":\"123890\"" +
"}";
HttpDriver.Instance.SendRequest(
url: "https://postman-echo.com/post", // 修正URL
type: HttpRequestType.POST,
onSuccess: (response) => {
Debug.Log($"注册成功:{response}");
},
onError: (error) => {
Debug.LogError($"注册失败:{error}");
},
headers: new Dictionary<string, string> {
{"Content-Type", "application/json"},
{"User-Agent", "Mozilla/5.0"},
//{"x-api-key", "reqres-free-v1"} // Added API key header
},
bodyData: postData
);
}
将提示信息以UI形式显示,创建UI提示信息面板,放入Resources文件夹的指定路径下,以提示邮箱填写为例,其代码更改如下:
cs
if (email.text == "")
{
//Debug.Log("需要填写邮箱");
GameObject page = Prefabs.Load("WebPrefabs/UI/Alert");
page.transform.Find("Image/Text").GetComponent<Text>().text = "需要填写邮箱";
return;
}
该面板下添加按钮点击事件,挂载脚本等工作就绪后运行如下:

点击注册按钮,由于判断语句顺序执行,所以优先提示填写邮箱(因仅作测试,故未设计UI):

该系列专栏为网课课程笔记,仅用于学习参考。