Unity 中的脚本响应不正确的值

Script in Unity responding incorrect values

我一直在尝试使用 weatherbit.io API 在我的 android 应用程序中访问 AQI 信息。 AqiInfoScript脚本用于访问API,Update AQI脚本用于打印值。

AqiInfoScript:

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using SimpleJSON;

public class AqiInfoScript : MonoBehaviour
{
    private float timer;
    public float minutesBetweenUpdate;
    private float latitude;
    private float longitude;
    private bool locationInitialized;
    public static string cityName;
    public static double currentAqi;

    private readonly string baseWeatherbitURL = "https://api.weatherbit.io/v2.0/current/airquality?";
    private readonly string key = "*********************";

    public void Begin()
    {
        latitude = GPS.latitude;
        longitude = GPS.longitude;
        locationInitialized = true;

    }
    void Update()
    {
        if (locationInitialized)
        {
            if (timer <= 0)
            {
                StartCoroutine(GetAqi());
                timer = minutesBetweenUpdate * 60;
            }
            else
            {
                timer -= Time.deltaTime;
            }
        }
    }
    private IEnumerator GetAqi()
    {
        string weatherbitURL = baseWeatherbitURL + "lat=" + latitude + "&lon=" + longitude + "&key=" 
        + key;
        UnityWebRequest aqiInfoRequest = UnityWebRequest.Get(weatherbitURL);

        yield return aqiInfoRequest.SendWebRequest();

        //error
        if (aqiInfoRequest.isNetworkError || aqiInfoRequest.isHttpError)
        {
            Debug.LogError(aqiInfoRequest.error);
            yield break;
        }

        JSONNode aqiInfo = JSON.Parse(aqiInfoRequest.downloadHandler.text);

        cityName = aqiInfo["city_name"];
        currentAqi = aqiInfo["data"]["aqi"];
    }
}

更新 AQI 脚本

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

public class UpdateAQI : MonoBehaviour
{
    public Text airquality;
    //public Text coordinates;

    private void Update()
    {
        airquality.text = "Current Aqi:  " + AqiInfoScript.currentAqi.ToString();
    }
}

当前输出:当前 AQI:0 期望输出:当前 AQI:129.0000

问题

在我看来 API returns 代表 your request 例如对于 lat=42, lon=-7 以下 JSON

{
    "data":[
               {
                   "mold_level":1,
                   "aqi":54,
                   "pm10":7.71189,
                   "co":298.738,
                   "o3":115.871,
                   "predominant_pollen_type":"Molds",
                   "so2":0.952743,
                   "pollen_level_tree":1,
                   "pollen_level_weed":1,
                   "no2":0.233282,
                   "pm25":6.7908,
                   "pollen_level_grass":1
               }
           ],
    "city_name":"Pías",
    "lon":-7,
    "timezone":"Europe\/Madrid",
    "lat":42,
    "country_code":"ES",
    "state_code":"55"
}

如你所见"data"实际上是一个数组。您将其视为单个值。

幕后花絮

不幸的是,您使用的 SmipleJson 库很容易出错,因为它不会因拼写错误而抛出任何异常,而是默默地失败并使用默认值。

你可以看到这个,例如在

public override JSONNode this[string aKey]
{
    get
    {
        if (m_Dict.ContainsKey(aKey))
            return m_Dict[aKey];
        else
            return new JSONLazyCreator(this, aKey);
    }
    ....
}

public static implicit operator double(JSONNode d)
{
    return (d == null) ? 0 : d.AsDouble;
}

解决方案

应该是

cityName = aqiInfo["city_name"];
currentAqi = aqiInfo["data"][0]["aqi"].AsDouble;

Debug.Log($"cityName = {cityName}\ncurrentAqi = {currentAqi}");

一般来说,我建议使用 JsonUtility.FromJson,而是在 C# 中实现所需的数据结构,例如:

[Serializable]
public class Data   
{
    public int mold_level;
    public double aqi;
    public double pm10;
    public double co;
    public double o3;
    public string predominant_pollen_type;
    public double so2;
    public int pollen_level_tree;
    public int pollen_level_weed;
    public double no2;
    public double pm25;
    public int pollen_level_grass;
}

[Serializable]
public class Root    
{
    public List<Data> data;
    public string city_name;
    public int lon;
    public string timezone;
    public int lat;
    public string country_code;
    public string state_code;
}

然后你会使用

var aqiInfo = JsonUtility.FromJson<Root>(aqiInfoRequest.downloadHandler.text);

cityName = aqiInfo.city_name;
currentAqi = aqiInfo.data[0].aqi;

Debug.Log($"cityName = {cityName}\ncurrentAqi = {currentAqi}");

对我来说,正如虚拟值所说 lat=42, lon=-7 两次都按预期打印出来

cityName = Pías
currentAqi = 54
UnityEngine.Debug:Log(Object)
<GetAqi>d__18:MoveNext() (at Assets/Example.cs:109)
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)