Unity3D网络通讯(三)-- HttpRestful请求的简单封装

时间:2022-07-24
本文章向大家介绍Unity3D网络通讯(三)-- HttpRestful请求的简单封装,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为2769,预计阅读7分钟

前言

上一篇《Unity3D网络通讯(二)--UnityWebRequest及JsonUtility请求Http Restful》已经实现了Unit3d使用UnityWebRequest与后台WebApi的Get和Post的通信,如果在正式做项目中,我们就不能按Demo的那样写法来调用了,所以这一篇针对UnityWebRequest做一个简单的封装。

实现思路

微卡智享

实现Http请求的封装,我们主要考虑的就是两个问题:

  1. 所有的网络通讯都写在一个类里,外部调用只考虑传入参数即可,做到解耦效果
  2. Unity的通讯是用协程方式实现网络通讯,怎么处理通讯返回的值后续的操作

第一个问题正常的封装都会考虑到这个,这里就不在说了,主要我们考虑的是第二个问题,因为是通过协程的方式处理网络通讯,没法实现我们正常封装只方法给出返回值的方式实现,所以这里应该用的就是传入回调函数的方式处理。所以这篇我们就用Action的方式解决这个问题。

代码实现

微卡智享

01

整理代码脚本

我们在Scripts下建了一个Model的文件夹(存放对象类)和一个Utils的文件夹(存放工具类),然后把WeatherForecase类移动到Model下,在Utils文件夹下再创建一个Network的文件夹,用于处理网络通讯,然后在这文件夹下创建一个HttpRestful的C#脚本。

02

HttpRestful封装

定义一个静态实例,然后写对应的实例方法获取方法。

写Get的协程方法调用,其中最后一个参数就是Action<bool, string>的方法,其中Action的第一个参数bool,用于返回通讯的成功或失败,第二个参数string是返回的通讯信息。

外部调用的Get方法传入的参数一样,内部是直接开户协程操作,下面的Post的实现也是按这个思路来写,只不过传入的参数里要加入一个我们传入的数据即可。

HttpRestful完整代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

public class HttpRestful : MonoBehaviour
{
    private static HttpRestful _instance;

    public static HttpRestful Instance
    {
        get
        {
            if(_instance == null)
            {
                GameObject goRestful = new GameObject("HttpRestful");
                _instance = goRestful.AddComponent<HttpRestful>();
            }
            return _instance;
        }
    }

    #region Get请求
    /// <summary>
    /// Get请求
    /// </summary>
    /// <param name="url"></param>
    /// <param name="actionResult"></param>
    public void Get(string url, Action<bool, string> actionResult = null)
    {
        StartCoroutine(_Get(url, actionResult));
    }

    private IEnumerator _Get(string url, Action<bool, string> action)
    {
        using (UnityWebRequest request = UnityWebRequest.Get(url))
        {
            yield return request.SendWebRequest();

            string resstr = "";
            if (request.isNetworkError || request.isHttpError)
            {
                resstr = request.error;
            }
            else
            {
                resstr = request.downloadHandler.text;
            }

            if (action != null)
            {
                action(request.isHttpError, resstr);
            }
        }
    }
    #endregion


    #region POST请求
    public void Post(string url, string data, Action<bool, string> actionResult = null)
    {
        StartCoroutine(_Post(url, data, actionResult));
    }

    private IEnumerator _Post(string url, string data, Action<bool, string> action)
    {
        using (UnityWebRequest request = new UnityWebRequest(url, "POST"))
        {
            request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(data));
            request.SetRequestHeader("content-type", "application/json;charset=utf-8");
            request.downloadHandler = new DownloadHandlerBuffer();

            yield return request.SendWebRequest();

            string resstr = "";
            if (request.isNetworkError || request.isHttpError)
            {
                resstr = request.error;
            }
            else
            {
                resstr = request.downloadHandler.text;
            }

            if (action != null)
            {
                action(request.isHttpError, resstr);
            }
        }
    } 
    #endregion
}

03

调用HttpRestful

我们重新复制了一个UIScripts,然后其中一个名字后面加上了Old,这样就是不用再重新设置了,我们直接在UIScripts脚本中改造即可。

首先定义一个Action<bool, string>,其中参数和HttpRestful里传入的Action方法是一样的。

然后增加一个InitAction的方法,里面对定义的actionRes写其的实现方法。方法中就是判断通讯如果失败直接显示文本,成功后进行处理,再显示处理后的数据,因为Get和Post调用后返回的数据类型是一样的,这样我们这里写了一个Action都可以调用这个方法进行后面的数据处理。

然后我们在Start里面首先把初始化Action进行调用,然后使用

HttpRestful.Instance.Get(url, actionRes);
HttpRestful.Instance.Post(url, json, actionRes);

就可以直接进行数据处理了,剩下的我们昨天调用的方法就可以都删除了。

UIScipts完整代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class UIScripts : MonoBehaviour
{
    [Header("按钮")]
    public Button btnget;
    public Button btngetparm;
    public Button btnjson;
    public Button btnpost;

    [Space]
    [Header("显示")]
    public Text txtshow;

    [Space]
    [Header("输入框")]
    public InputField edturl;
    public InputField edtparm;

    //定义一个返回数据的Action
    private Action<bool, string> actionRes;
    // Start is called before the first frame update
    void Start()
    {
        InitAction();

        //Get按钮操作
        btnget.onClick.AddListener(() =>
        {
            Debug.Log(edturl.text);
            string url = edturl.text;
            HttpRestful.Instance.Get(url, actionRes);
        });
        btngetparm.onClick.AddListener(() =>
        {
            string url = edturl.text;
            string param = edtparm.text;

            string allurl = url + "/Info?Summary=" + param;
            HttpRestful.Instance.Get(allurl, actionRes);
        });

        btnjson.onClick.AddListener(() => StartCoroutine(JsonConvert()));

        btnpost.onClick.AddListener(() =>
        {
            WeatherForecast item = new WeatherForecast();
            item.Summary = "Alvin";
            item.Date = DateTime.Now;
            item.TemperatureC = 10;
            item.TemperatureF = 20;
            string json = JsonUtility.ToJson(item);

            string url = edturl.text + "/Reg";
            Debug.Log(url);
            HttpRestful.Instance.Post(url, json, actionRes);
        });
    }

    /// <summary>
    /// 写返回Action的处理方法
    /// </summary>
    private void InitAction()
    {
        actionRes = new Action<bool, string>((bl, str) =>
        {
            if (bl)
            {
                txtshow.text = str;
            }
            else
            {
                string resjson = "{"array":" + str + "}";
                txtshow.text = resjson;
                WeatherData lists = JsonUtility.FromJson<WeatherData>(resjson);
                StringBuilder sb = new StringBuilder();
                foreach (WeatherForecast item in lists.array)
                {
                    sb.Append("Date:" + item.Date + " Summary:" + item.Summary + " TemperatureF:"
                        + item.TemperatureF + "TemperatureC:" + item.TemperatureC + "rn");
                }
                txtshow.text = sb.ToString();
            }
        });
    }

    IEnumerator JsonConvert()
    {
        WeatherForecast item = new WeatherForecast();
        item.Summary = "Alvin";
        item.Date = DateTime.Now;
        item.TemperatureC = 10;
        item.TemperatureF = 20;

        string json = JsonUtility.ToJson(item);
        txtshow.text = json;
        yield return new WaitForSeconds(3f);

        WeatherForecast newitem = JsonUtility.FromJson<WeatherForecast>(json);
        string showtext = "Summary:" + newitem.Summary + "  Date:" + newitem.Date +
            "  C:" + newitem.TemperatureC + "  F:" + newitem.TemperatureF;
        txtshow.text = showtext;
    }
}

实现效果

上图就是封装后调用WebApi的实现效果,后面我又在Android平台下进行了编译,调用也完全没有问题,这种方式可以跨平台使用的。

扫描二维码

获取更多精彩

微卡智享

「 往期文章 」

Unity3D网络通讯(二)--UnityWebRequest及JsonUtility请求Http Restful

Unity3D网络通讯(一)--Asp.Net Core WebApi创建发布注意事项

Unity3D使用Cinemachine配合Timeline实现运镜效果