Unity对接后台和加载图片

1、前言

        在unity中与后台对接,用await在web端暂时还不支持,所以,协程成为比较好的通用方式,以下适用除post访问外的所有对接

2、对接后台
2.1、安装插件

        首先我们需要用到Newtonsoft.dll,如果没有这个.dll的请跟着我一起装上,我们先创建一个脚本WebRequest.cs,然后双击脚本打开VS2022

在上面一排工具栏中,点击“工具”选项

 选择NuGet包管理器-管理解决方案的NuGet程序包,这时会弹出一个窗口

点击”浏览“

排在第一的就是我们需要用的插件,插件轻量好用

点击这个后,右侧小窗弹出窗口,像我这样勾选,然后安装

 安装完成后,我们回到脚本页面,右键打开所在的文件夹

我们返回工程目录,在Packages这个文件夹下有一个Newtonsoft文件夹,这个就是我们的插件

点进文件夹后有许多net版本,个人比较推荐netstandard2.0

 将netstandard2.0下的Newtonsoft.Json.dll拖入我们的工程里,下面开始我们的正文

2.2、代码

        回到正题,我们创建好WebRequest.cs后,结构是这样

using Newtonsoft.Json.Linq;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class WebRequest : MonoBehaviour
{
    public string address;
    // Start is called before the first frame update
    void Start()
    {
        
    }
    /// <summary>
    /// 获取返回对象,如果不存在返回为null
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="path">路径</param>
    /// <param name="callback"></param>
    /// <returns></returns>
    public IEnumerator RequestURLWithArray(string path, System.Action<JObject> callback)
    {
        string paths = address + path;
        Debug.LogError("当前链接+++" + paths);
        //jishi();
        using (var request = UnityWebRequest.Get(paths))
        {
            // 发送HTTP请求并等待响应
            yield return request.SendWebRequest();

            // 检查是否有错误发生
            if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
            {
                Debug.LogError(request.error + "链接:" + paths);
                yield break;
            }
            if (!string.IsNullOrEmpty(request.downloadHandler.text))
            {

                callback(JObject.Parse(request.downloadHandler.text));
            }

        }
    }
}

由于是教学,我没有现有的后台接口,就用本地json代替,后台对接也只是换一下链接就能继续用

以上代码写完,我们在工程目录Assets下创建StreamingAssets文件夹,在StreamingAssets文件夹中创建“测试.json”,测试.json的数据结构如下:

{
"name":"11111",
"id":123456789,
"password":"123456789"
}

兄弟们一定一定要注意,json必须是utf8格式保存的,不然容易出现读取失败或者乱码等bug

一个非常简单的json,主要是测试用,打算搭一个登录界面来测试所以数据不多,如果兄弟们有大量数据的,也可以用这套东西,博主亲测,几十个接口+几百条数据,完美对接,延时基本上在几百ms,可以接受的

然后我们在WebRequest的Start里写获取,改写一下WebRequest

using Newtonsoft.Json.Linq;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class WebRequest : MonoBehaviour
{
    public string address;
    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(RequestURLWithArray(Application.streamingAssetsPath + "/测试.json", (a) =>
        {
            Debug.Log($"name:{a["name"]} id: {a["id"]} password: {a["password"]}");
        }));
    }
    /// <summary>
    /// 获取返回对象,如果不存在返回为null
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="path">路径</param>
    /// <param name="callback"></param>
    /// <returns></returns>
    public IEnumerator RequestURLWithArray(string path, System.Action<JObject> callback)
    {
        string paths =  path;
        Debug.LogError("当前链接== " + paths);
        //jishi();
        using (var request = UnityWebRequest.Get(paths))
        {
            // 发送HTTP请求并等待响应
            yield return request.SendWebRequest();

            // 检查是否有错误发生
            if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
            {
                Debug.LogError(request.error + "链接:" + paths);
                yield break;
            }
            if (!string.IsNullOrEmpty(request.downloadHandler.text))
            {

                callback(JObject.Parse(request.downloadHandler.text));
            }

        }
    }
}

到这里就要注意,敲黑板划重点

我在这里写的输出,是转成JObject对象后以键对值的形式直接取得

Debug.Log($"name:{a["name"]} id: {a["id"]} password: {a["password"]}");

这里的键全部要和json中的变量对的上,才能获取到,当然,除了JObject外还有数组形式,那是另一种结构,我们等下再说

写完后保存,回到unity中,创建空对象 WebRequest将脚本挂在上面,开始运行

这时控制台就会输出我们想要的数据:

以上就是基础用法,不太建议这样用,如果是只有一个json或接口,可以像上述这样写,但是如果不止一个,而且数据多,我们就要换种形式读取

2.3、进阶用法

        接下来是进阶用法,我们先创建一个抽象类,这个类继承MonoBehaviour,并且要有一个封装好的JObject参数,一个虚方法init,用来处理收到的数据:

1、新建抽象类Dataabstract.cs

using Newtonsoft.Json.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class Dataabstract : MonoBehaviour
{
    public string path;
    protected JObject data;
    public JObject Data
    {
        get { return data; }
        set 
        { 
            if (value != null)
            {
                data = value;
                init();
            }
            else
            {
                Debug.LogError("获取失败,请检查链接地址");
            }
        }
    }
    protected virtual void init()
    {

    }
}

2、修改WebRequest.cs

using Newtonsoft.Json.Linq;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class WebRequest : MonoBehaviour
{
    public string address = Application.streamingAssetsPath;
    public Dataabstract[] Dataabstracts;
    // Start is called before the first frame update
    void Start()
    {
        init();
    }
    void init()
    {
        for (int i = 0; i < Dataabstracts.Length; i++)
        {
            StartCoroutine(RequestURLWithArray(address+"/"+Dataabstracts[i].path, (a) =>
            {
                Dataabstracts[i].Data = a;
            }));
        }
    }
    /// <summary>
    /// 获取返回对象,如果不存在返回为null
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="path">路径</param>
    /// <param name="callback"></param>
    /// <returns></returns>
    public IEnumerator RequestURLWithArray(string path, System.Action<JObject> callback)
    {
        string paths =  path;
        Debug.LogError("当前链接== " + paths);
        //jishi();
        using (var request = UnityWebRequest.Get(paths))
        {
            // 发送HTTP请求并等待响应
            yield return request.SendWebRequest();

            // 检查是否有错误发生
            if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
            {
                Debug.LogError(request.error + "链接:" + paths);
                yield break;
            }
            if (!string.IsNullOrEmpty(request.downloadHandler.text))
            {
                callback(JObject.Parse(request.downloadHandler.text));
            }

        }
    }
}

3、新建测试类Test1,Test1继承抽象类Dataabstract重写init方法

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test1 : Dataabstract
{
    protected override void init()
    {
        Debug.Log($"name:{data["name"]} id: {data["id"]} password: {data["password"]}");
    }
}

回到unity中,新建空物体Test1,挂上Test1脚本,在面板上的path写上我们的json名字,请注意,一定要把          后缀带上,后缀带上,后缀带上

然后我们把Test1拖入WebRequest的Dataabstracts数组中

然后运行就可以看到我们拿到了数据

这样主要是应对大量不同的json或接口要读的, 这是这种格式的多样,下面我们来看另一种格式的json

2.4、另一种带数组的json读取

我们在StreamingAssets下再创建一种json,名字叫测试1.json,数据如下

{
  "data": [
    {
      "name": "123",
      "id": 1,
      "password": "爱上放大"
    },
    {
      "name": "456",
      "id": 2,
      "password": "各色地方"
    },
    {
      "name": "789",
      "id": 3,
      "password": "奥尔格和"
    }
  ]
}

新建Test2脚本

using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.UI;

public class Test2 : Dataabstract
{
    public int index;
    [SerializeField] Text[] text;
    protected override void init()
    {
        JArray jArray = (JArray)data["data"];
        for (int i = 0; i < text.Length; i++)
        {
            text[i].text = jArray[index][text[i].name].ToString();
        }
    }
}

接下来我们回到unity,按我这样的结构创建好东西

把Test2挂到GameObject上,然后各GameObject的index分开,我这里的json有三组数据,所以我这里填的是0-2,这个作为索引去json中的data数组中找数据而已,将每个GameObject下的三个Text拖进Test2中的Text数组中

 然后把三个挂了Test2的GameObject拖进WebRequest中的数组中

直接运行就能看到结果 

可以看到,我们成功取到了数据,而且几乎没有延时,基本上是运行就有

2.5、总结

在面对如下简单的json时,我们用JObject去拿数据

{
  "name": "11111",
  "id": 123456789,
  "password": "123456789"
}

在面对如下稍微复杂的json时,我们用JArray取数据

{
  "data": [
    {
      "name": "123",
      "id": 1,
      "password": "爱上放大"
    },
    {
      "name": "456",
      "id": 2,
      "password": "各色地方"
    },
    {
      "name": "789",
      "id": 3,
      "password": "奥尔格和"
    }
  ]
}

而我们建的抽象类,只是用了一个简易版的观察者模式,去构建我们的通信模块,方便维护,降低耦合

3、加载图片
public void show(string url,Action<Sprite> ac)
{
    StartCoroutine(LoadImageFromUrl(url,ac));
}
IEnumerator LoadImageFromUrl(string url, Action<Sprite> ac)
{
    using (var request = UnityWebRequestTexture.GetTexture(url))
    {
        yield return request.SendWebRequest();

        if (request.result != UnityWebRequest.Result.Success)
        {
            Debug.Log(request.error);
        }
        else
        {
            Texture2D texture = DownloadHandlerTexture.GetContent(request);
            Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
            ac(sprite);
        }
    }
}

我们可以建一个脚本来测试这段代码,新建Test3

using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class Test3 : MonoBehaviour
{
    [SerializeField] Image im;
    private void Start()
    {
        show("https://img1.baidu.com/it/u=4049022245,514596079&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1701622800&t=c88ca2191a6df508642839cff923ed20", (a) =>
        {
            im.sprite = a;
        });
    }
    public void show(string url,Action<Sprite> ac)
    {
        StartCoroutine(LoadImageFromUrl(url,ac));
    }
    IEnumerator LoadImageFromUrl(string url, Action<Sprite> ac)
    {
        using (var request = UnityWebRequestTexture.GetTexture(url))
        {
            yield return request.SendWebRequest();

            if (request.result != UnityWebRequest.Result.Success)
            {
                Debug.Log(request.error);
            }
            else
            {
                Texture2D texture = DownloadHandlerTexture.GetContent(request);
                Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
                ac(sprite);
            }
        }
    }
}

回到unity,新建一个Image,把Test3挂上去,运行

 可以看到图片已经加载出来了,非常好用,当然这个图片如果多的话可以参考上面读json的形式改写,建立一个图片管理模块去专门加载图片,我们下期再见

猜你喜欢

转载自blog.csdn.net/k253316/article/details/134753300
今日推荐