You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity C#读取含多层子键的JSON字典问题求助

在Unity中读取多层字典结构JSON并实现玩家位置同步

问题背景

尝试用C#脚本在Unity中读取JSON数据,目标是基于位置数据同步移动玩家。需要在Update()前按字典键对嵌套字典分组,此前普通数组结构的JSON可正常读取,但多层字典结构的JSON处理时出现CS0029(隐式转换错误)和CS1061(List无Keys属性)错误。

可正常读取的JSON格式

{"__comment__": "This file contains event and positional information. Data generated on 2024-07-14 17:51:10. Version: 1.0.0.","event_data": [{"player_name": "player1","league_id": "xxxx","team": 2,"x": 26.68,"y": 9.179,"z": 1.6,"match_time_seconds_column": 1,"event_key": 1},{"player_name": "player2","league_id": "xxxx","team": 2,"x": 19.109,"y": 9.189,"z": 1.6,"match_time_seconds_column": 1,"event_key": 1}]}

无法正确处理的多层字典JSON格式

{"__comment__": "This file contains event and positional information grouped by match time seconds. Data generated on 2024-07-14 17:51:10. Version: 1.0.0.","event_data": {"1": {"1": [{"player_name": "player1","league_id": "xxxx","team": 2,"x": 26.68,"y": 9.179,"z": 1.6,"match_time_seconds_column": 1,"event_key": 1},{"player_name": "player2","league_id": "xxxx","team": 2,"x": 19.109,"y": 9.189,"z": 1.6,"match_time_seconds_column": 1,"event_key": 1},{"player_name": "player3","league_id": "xxx","team": 2,"x": 23.204,"y": 8.801,"z": 1.6,"match_time_seconds_column": 1,"event_key": 1}]},"34": {"873": [{"player_name": "player4","league_id": "xxxx","team": 1,"x": 39.344,"y": 19.727,"z": 1.6,"match_time_seconds_column": 873,"event_key": 34}]}}}

原代码问题

原代码混用JsonUtility和Newtonsoft.Json,且后续遍历逻辑错误(试图访问List的Keys属性),导致类型转换和属性不存在的错误。


正确实现方案

1. 定义匹配JSON结构的实体类

确保EventPositionalData类字段与JSON中玩家数据的键完全对应,同时RootObject的event_data类型匹配多层字典结构:

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

public class DataReader3 : MonoBehaviour
{
    // 玩家位置数据实体类
    [System.Serializable]
    public class EventPositionalData
    {
        public string player_name;
        public string league_id; // 若JSON中为数字类型,改为int
        public int team;
        public float x;
        public float y;
        public float z;
        public int match_time_seconds_column;
        public int event_key;
    }

    // 根对象类,匹配多层字典结构的JSON
    public class RootObject
    {
        public string __comment__;
        public Dictionary<string, Dictionary<string, List<EventPositionalData>>> event_data;
    }

    public TextAsset jsonFile; // 在Inspector中拖入JSON文件

    private RootObject parsedData;
    // 预分组存储,方便Update快速获取
    private Dictionary<string, List<EventPositionalData>> groupedData = new Dictionary<string, List<EventPositionalData>>();

    void Start()
    {
        // 仅用Newtonsoft.Json反序列化多层字典结构
        parsedData = JsonConvert.DeserializeObject<RootObject>(jsonFile.text);
        
        // 在Update前完成预分组
        PreGroupData();
    }

    // 预分组逻辑:按event_key+match_time_seconds_column整理数据
    void PreGroupData()
    {
        // 遍历外层event_key字典
        foreach (var eventKeyValuePair in parsedData.event_data)
        {
            string eventKey = eventKeyValuePair.Key;
            var timeDict = eventKeyValuePair.Value;

            // 遍历内层match_time字典
            foreach (var timeKeyValuePair in timeDict)
            {
                string matchTime = timeKeyValuePair.Key;
                List<EventPositionalData> playerList = timeKeyValuePair.Value;

                // 用eventKey+matchTime作为唯一键存储玩家列表
                groupedData[$"{eventKey}_{matchTime}"] = playerList;
            }
        }
    }

    void Update()
    {
        // 示例:根据当前游戏状态获取对应玩家列表并同步位置
        string targetKey = "1_1"; // 假设当前需要同步eventKey=1、matchTime=1的玩家
        if (groupedData.TryGetValue(targetKey, out var players))
        {
            foreach (var playerData in players)
            {
                // 根据player_name找到对应玩家对象,设置位置
                // GameObject playerObj = GameObject.Find(playerData.player_name);
                // if (playerObj != null)
                // {
                //     playerObj.transform.position = new Vector3(playerData.x, playerData.y, playerData.z);
                // }
            }
        }
    }
}

2. 关键修正点

  • 统一序列化工具:多层字典结构不适合Unity内置的JsonUtility,全程使用Newtonsoft.Json(需通过Unity Package Manager搜索导入Newtonsoft Json包)。
  • 字段严格匹配:C#类的字段名必须与JSON中的键完全一致,若需改名可使用[JsonProperty("json_key_name")]特性指定。
  • 正确遍历嵌套字典:外层遍历event_key字典,内层遍历match_time字典,最终获取玩家列表,避免错误访问List的Keys属性。

3. 常见错误规避

  • 禁止混用JsonUtility和Newtonsoft.Json:前者对复杂嵌套结构支持有限,后者更适合处理多层字典JSON。
  • 类型匹配检查:确保JSON中的数据类型与C#字段类型一致(如浮点数对应float,整数对应int,字符串对应string)。

内容的提问来源于stack exchange,提问作者Vintertid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 02:15:02