如何使用C#在Unity中将OpenWeatherMap城市JSON填充到下拉列表
我来帮你一步步搞定这个需求,流程其实很清晰,主要分为定义数据模型、处理JSON格式、读取解析数据、填充Dropdown这几个环节,下面是具体细节:
1. 定义JSON对应的数据模型类
Unity自带的JsonUtility需要序列化类来映射JSON结构,我们先创建两个序列化类,完全匹配你给出的城市和坐标字段:
using UnityEngine; // 坐标数据模型 [System.Serializable] public class Coord { public float lon; public float lat; } // 城市数据模型 [System.Serializable] public class City { public int id; public string name; public string country; public Coord coord; } // 辅助类:解决Unity JsonUtility不支持直接解析顶级JSON数组的问题 public static class JsonHelper { public static T[] FromJson<T>(string json) { // 给顶级数组套一层对象包装 string wrappedJson = "{\"items\":" + json + "}"; Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(wrappedJson); return wrapper.items; } [System.Serializable] private class Wrapper<T> { public T[] items; } }
2. 修正JSON文件格式
你给出的示例是多个独立的城市对象,需要把它们放到数组括号里,变成标准的JSON数组格式(否则解析会失败):
[
{ "id": 2163306, "name": "Holgate", "country": "AU", "coord": { "lon": 151.416672, "lat": -33.400002 } },
{ "id": 2164949, "name": "Gooramadda", "country": "AU", "coord": { "lon": 146.550003, "lat": -36 } },
{ "id": 2157716, "name": "Miepoll", "country": "AU", "coord": { "lon": 145.466675, "lat": -36.616669 } },
{ "id": 2148406, "name": "Steiglitz", "country": "AU", "coord": { "lon": 144.183334, "lat": -37.883331 } }
]
将修正后的文件命名为cities.json,放到Unity项目的Assets/Resources文件夹下(没有的话直接新建一个Resources文件夹即可)。
3. 编写填充Dropdown的核心脚本
创建一个C#脚本,挂载到包含Dropdown组件的GameObject上,代码如下:
using UnityEngine; using UnityEngine.UI; using System.Collections.Generic; public class CityDropdownFiller : MonoBehaviour { // 在Inspector面板中拖入你的Dropdown组件 public Dropdown cityDropdown; void Start() { FillCityDropdown(); } private void FillCityDropdown() { // 从Resources读取JSON文件 TextAsset jsonText = Resources.Load<TextAsset>("cities"); if (jsonText == null) { Debug.LogError("找不到cities.json文件,请检查文件路径和名称"); return; } // 解析JSON为City数组 City[] cities = JsonHelper.FromJson<City>(jsonText.text); if (cities == null || cities.Length == 0) { Debug.LogError("JSON解析失败,或者文件中没有有效城市数据"); return; } // 清空Dropdown原有选项 cityDropdown.options.Clear(); // 将城市名称添加到Dropdown选项列表 List<Dropdown.OptionData> options = new List<Dropdown.OptionData>(); foreach (City city in cities) { // 可以选择显示"城市名(国家码)",比如Holgate(AU),按需调整 options.Add(new Dropdown.OptionData(city.name)); } cityDropdown.AddOptions(options); } }
4. 编辑器配置与测试
- 在Unity编辑器中,选中挂载了上述脚本的GameObject;
- 在Inspector面板中,将你的Dropdown组件拖到脚本的
cityDropdown字段上; - 运行游戏,就能看到Dropdown里已经填充好所有城市名称了。
额外优化:大文件异步加载
如果你的城市JSON文件很大(比如包含全球城市),同步加载可能导致游戏卡顿,建议改用异步方式从StreamingAssets文件夹读取:
using System.IO; using UnityEngine.Networking; using System.Collections; // 在原脚本中添加这个协程方法 private IEnumerator FillCityDropdownAsync() { string filePath = Path.Combine(Application.streamingAssetsPath, "cities.json"); UnityWebRequest request = UnityWebRequest.Get(filePath); yield return request.SendWebRequest(); if (request.result != UnityWebRequest.Result.Success) { Debug.LogError("加载JSON失败:" + request.error); } else { string jsonText = request.downloadHandler.text; City[] cities = JsonHelper.FromJson<City>(jsonText); // 后续填充Dropdown的逻辑和之前一致 cityDropdown.options.Clear(); List<Dropdown.OptionData> options = new List<Dropdown.OptionData>(); foreach (City city in cities) { options.Add(new Dropdown.OptionData(city.name)); } cityDropdown.AddOptions(options); } } // 记得把Start方法里的FillCityDropdown()改成StartCoroutine(FillCityDropdownAsync())
内容的提问来源于stack exchange,提问作者Alina

