【问题标题】:Script in Unity responding incorrect valuesUnity 中的脚本响应不正确的值
【发布时间】:2023-03-21 21:39:01
【问题描述】:

我一直在尝试使用 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

【问题讨论】:

  • 你确定Begin被调用了吗?在currentAqi = aqiInfo["data"]["aqi"]; 之后可以添加Debug.Log($"New data available: ${currentAqi}"); 吗?您是否也尝试过明确致电 agiInfo["data"]["aqi"].AsDouble ? ..你也不应该在这里发布真正的钥匙
  • 一般来说,我不会在Update 中这样做,而是更多地由事件驱动。下载完成或失败后开始下一次下载。仅在收到新数据时才更新文本组件
  • 1. GPS 脚本中已经存在 Begin 函数为 aqiInfoScript.Begin(); 2。我添加了 Debug.Log 3。也显式调用了 agiInfo["data"]["aqi"] ,并且它们都呈现与之前相同的结果 4。我很抱歉关键,我已经为此苦苦挣扎了好几天,我完全忘记了关键 5。关于您的第二个查询,我首先想确保在清理代码之前我实际上正在获取数据,但这甚至没有发生用最简单的程序:(
  • 但只是为了确保这意味着它与您的第二个脚本无关,但错误已经存在于您从 API 收到的数据中......您是否 100% 确定没有错字currentAqi = aqiInfo["data"]["aqi"]; 的密钥?收到的 json 是否有完全匹配字段名称?你能告诉我们Debug.Log(aqiInfoRequest.downloadHandler.text); 的输出吗?
  • 以下是weatherbit.io主页的链接,其中包含示例JSON文件https://www.weatherbit.io/api/airquality-current#:~:text=This%20Air%20Quality%20API%20returns,(USA%20and%20EU%20only),我已经检查了一遍又一遍。 aqi 属于 data 类。没有匹配的字段名称。

标签: c# android api unity3d game-engine


【解决方案1】:

问题

在我看来,API 返回 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)

【讨论】:

  • 我在Start 的示例脚本中使用了您的确切GetAqi,并且只是硬编码了lat=42;lon=-7; 如果我再做Debug.Log($"cityName = {cityName}\ncurrentAqi = {currentAqi}");,我得到了预期的打印.. 不管哪个我使用的两个 json 库中的一个。
  • 非常感谢@derHugo。该应用程序仍然返回Current Aqi: 0,但现在我将尝试JSONUtility 并以这种方式实现它。我有一个疑问,这可能与这里相关,也可能不相关,但是 weatherbit.io 的内容类似于 所有参数都应作为查询字符串参数提供给 Air Quality API。 ,这可能是一些问题排序?
  • 很抱歉问这个问题,但“开始”是什么意思?我应该把我的代码放在 void start() 中吗?我现在很恐慌!
  • 我使用了Start,因为这是在应用程序启动时自动调用的......只是为了测试......如果你说你在某个地方调用Begin那么它应该没问题......做您是否从下载例程中获得了调试日志? .. 可能你的日常工作从未开始
  • 是的,一旦我从GPS 脚本中获得纬度/经度值,我就会调用Begin。我测试并发现它准确地捕获了纬度/经度值。我会尝试将我的Coroutine 放入Begin 本身,看看它是否会变得更好。不,我没有得到任何调试文件,因为我手动构建 APK 并将其发送到我的手机。您有什么建议吗?或许我应该彻底摧毁整个事情,从头开始。
猜你喜欢
  • 1970-01-01
  • 2023-01-11
  • 1970-01-01
  • 2020-11-03
  • 1970-01-01
  • 1970-01-01
  • 2017-06-25
  • 1970-01-01
  • 2020-08-08
相关资源
最近更新 更多