Unity的HTTP请求类使用方法+Unity整合接口

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):

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

相关推荐
海尔辛1 小时前
学习黑客 week1周测 & 复盘
网络·学习·web安全
现实与幻想~1 小时前
Linux:web服务
linux·服务器·网络
Leoysq2 小时前
为 Unity 项目添加自定义 USB HID 设备支持 (适用于 PC 和 Android/VR)-任何手柄、无人机手柄、摇杆、方向盘
android·unity·vr
SRC_BLUE_172 小时前
攻防世界 - Misc - Level 6 | Wireshark
网络·测试工具·wireshark
珹洺3 小时前
Linux操作系统从入门到实战(五)详细讲解Linux权限概念
linux·运维·服务器·网络
萧瑟其中~3 小时前
计算机网络:详解TCP协议(四次握手三次挥手)
网络·tcp/ip·计算机网络
~央千澈~4 小时前
MCP协议深度解析:原理、应用与物联网时代的机遇-优雅草卓伊凡
网络·网络协议
music score4 小时前
Keysight万用表使用指南及基于Python采集数据生成Excel文件
开发语言·网络·python
落——枫5 小时前
组网技术知识点
网络