Unity json反序列化为 字典存储

当在Unity游戏中需要加载和管理游戏数据,通常使用JSON文件是一种常见的方法。在本篇博客中,我们将深入探讨如何使用C#和Unity的JSON反序列化功能来实现这一目标。我们可以使用Unity的JsonUtility来反序列化JSON数据并将其映射到自定义的C#数据结构中。

首先,让我们来创建一些数据类,以便加载和管理游戏中的角色和武器数据。在这个示例中,我们将使用Player(角色)、Monster(怪物)和WeaponData(武器数据)这三种数据类型。

{
  "players": [
    {
      "id": "1",
      "name": "player0",
      "weaponID": "102",
      "maxHp": "50",
      "damage": "0",
      "defense": "0",
      "moveSpeed": "5.0",
      "coolDown": "0",
      "amount": "0"
    },
    {
      "id": "2",
      "name": "player1",
      "weaponID": "101",
      "maxHp": "40",
      "damage": "-10",
      "defense": "0",
      "moveSpeed": "5",
      "coolDown": "20",
      "amount": "0"
    },
    {
      "id": "3",
      "name": "player2",
      "weaponID": "101",
      "maxHp": "50",
      "damage": "20",
      "defense": "1",
      "moveSpeed": "5.0",
      "coolDown": "-50",
      "amount": "1"
    },
    {
      "id": "4",
      "name": "player3",
      "weaponID": "102",
      "maxHp": "50",
      "damage": "-50",
      "defense": "-1",
      "moveSpeed": "6",
      "coolDown": "100",
      "amount": "0"
    }
  ]
} 

我们需要创建了具有与JSON数据匹配的数据结构。这些类使用[Serializable]特性,以便能够进行JSON序列化和反序列化

[Serializable]
	public class Monster
    {
		public int id;
		public string name;
		public int maxHp;
		public int damage;
		public int defense;
		public float moveSpeed;
		public int expMul;
	}`在这里插入代码片`

通过观察JSON文件我们发现,这个JSON文件示例是一个包含多个玩家信息的数组。

[Serializable]
	public class PlayerData
	{
		public List<Player> players = new List<Player>();
	}

我们可以用一个玩家数据结构的数组去存储这个json文件,并

TextAsset textAsset = Managers.Resource.Load<TextAsset>($"Data/PlayerData");
PlayerData []players JsonUtility.FromJson<Loader>(textAsset.text);

去解析并且遍历它放到字典里,
当我们要解析的json特别多时 我们定义了一个泛型方法LoadJson,该方法负责加载JSON数据并将其反序列化为具体类型的字典。这个方法接受一个Loader类型,该类型必须实现ILoader接口。

 Loader LoadJson<Loader, Key, Value>(string path) where Loader : ILoader<Key, Value>
    {
        TextAsset textAsset = Managers.Resource.Load<TextAsset>($"Data/{path}");
        return JsonUtility.FromJson<Loader>(textAsset.text);
    }

ILoader接口

public interface ILoader<Key, Value>
{
    Dictionary<Key, Value> MakeDict();
}

我们让存储具有JSON数据结构的数组继承该接口

	[Serializable]
	public class PlayerData : ILoader<int, Player>
	{
		public List<Player> players = new List<Player>();

		public Dictionary<int, Player> MakeDict()
		{
			Dictionary<int, Player> dict = new Dictionary<int, Player>();
			foreach (Player player in players)
				dict.Add(player.id, player);
			return dict;
		}
	}

这样就可以将JSON文件反序列化放在数组中

 public Dictionary<int, Data.WeaponData> WeaponData { get; private set; } = new Dictionary<int, Data.WeaponData>();
    public Dictionary<int, Data.Player> PlayerData { get; private set; } = new Dictionary<int, Data.Player>();
    public Dictionary<int, Data.Monster> MonsterData { get; private set; } = new Dictionary<int, Data.Monster>();

    public void Init()
    {
        PlayerData = LoadJson<Data.PlayerData, int, Data.Player>("PlayerData").MakeDict();
        WeaponData = LoadJson<Data.WeaponDataLoader, int, Data.WeaponData>("WeaponData").MakeDict();
        MonsterData = LoadJson<Data.MonsterData, int, Data.Monster>("MonsterData").MakeDict();
        
    }

代码如下

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

public interface ILoader<Key, Value>
{
    Dictionary<Key, Value> MakeDict();
}

public class DataManager
{
    public Dictionary<int, Data.WeaponData> WeaponData { get; private set; } = new Dictionary<int, Data.WeaponData>();
    public Dictionary<int, Data.Player> PlayerData { get; private set; } = new Dictionary<int, Data.Player>();
    public Dictionary<int, Data.Monster> MonsterData { get; private set; } = new Dictionary<int, Data.Monster>();

    public void Init()
    {
        PlayerData = LoadJson<Data.PlayerData, int, Data.Player>("PlayerData").MakeDict();
        WeaponData = LoadJson<Data.WeaponDataLoader, int, Data.WeaponData>("WeaponData").MakeDict();
        MonsterData = LoadJson<Data.MonsterData, int, Data.Monster>("MonsterData").MakeDict();
        
    }

    Loader LoadJson<Loader, Key, Value>(string path) where Loader : ILoader<Key, Value>
    {
        TextAsset textAsset = Managers.Resource.Load<TextAsset>($"Data/{path}");
        return JsonUtility.FromJson<Loader>(textAsset.text);
    }

}

在DataManager的Init方法中,我们加载并初始化了游戏数据,包括角色数据、武器数据和怪物数据。通过调用LoadJson泛型方法,我们可以轻松地加载各种类型的JSON数据并将其转化为字典对象。

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

namespace Data
{
	#region Character

	[Serializable]
	public class Player
	{
		public int id;
		public string name;
		public int weaponID;
		public int maxHp;
		public int damage;
		public int defense;
		public float moveSpeed;
		public int coolDown;
		public int amount;
	}

	[Serializable]
	public class PlayerData : ILoader<int, Player>
	{
		public List<Player> players = new List<Player>();

		public Dictionary<int, Player> MakeDict()
		{
			Dictionary<int, Player> dict = new Dictionary<int, Player>();
			foreach (Player player in players)
				dict.Add(player.id, player);
			return dict;
		}
	}

    #endregion

    #region Monster

	[Serializable]
	public class Monster
    {
		public int id;
		public string name;
		public int maxHp;
		public int damage;
		public int defense;
		public float moveSpeed;
		public int expMul;
	}

    public class MonsterData : ILoader<int, Monster>
    {
		public List<Monster> monsters = new List<Monster>();
        public Dictionary<int, Monster> MakeDict()
        {
			Dictionary<int, Monster> dict = new Dictionary<int, Monster>();
			foreach (Monster monster in monsters)
				dict.Add(monster.id, monster);
			return dict;
		}
    }


    #endregion
    #region Weapon

    [Serializable]
	public class WeaponData
    {
        public int weaponID;
        public string weaponName;
        public List<WeaponLevelData> weaponLevelData = new List<WeaponLevelData>();

	}

	[Serializable]
	public class WeaponLevelData
	{
		public int level;
		public int damage;
		public float movSpeed;
		public float force;
		public float cooldown;
		public float size;
		public int penetrate;
		public int countPerCreate;
	}

	[Serializable]
	public class WeaponDataLoader : ILoader<int, WeaponData>
	{
		public List<WeaponData> weapons = new List<WeaponData>();
        public Dictionary<int, WeaponData> MakeDict()
        {
            Dictionary<int, WeaponData> dict = new Dictionary<int, WeaponData>();
            foreach (WeaponData weapon in weapons)
                dict.Add(weapon.weaponID, weapon);
            return dict;
        }
    }
	#endregion

}

通过使用Unity的JsonUtility和C#的泛型方法,我们可以方便地加载和管理游戏数据。这种方法对于处理不同类型的数据非常有用,而且代码可复用性很高。希望这篇博客对你了解Unity中的JSON反序列化和数据管理有所帮助。如果你有任何问题或需要进一步的指导,请随时在评论中提问!

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以使用如下代码实现: ``` using Newtonsoft.Json; using System.Collections.Generic; public class MyDictionaryConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Dictionary<,>); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var dictionary = (IDictionary)value; var keyType = dictionary.GetType().GetGenericArguments()[0]; var valueType = dictionary.GetType().GetGenericArguments()[1]; writer.WriteStartObject(); foreach (var key in dictionary.Keys) { writer.WritePropertyName(JsonConvert.SerializeObject(key)); serializer.Serialize(writer, dictionary[key]); } writer.WriteEndObject(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var dictionary = (IDictionary)Activator.CreateInstance(objectType); var keyType = objectType.GetGenericArguments()[0]; var valueType = objectType.GetGenericArguments()[1]; while (reader.Read() && reader.TokenType == JsonToken.PropertyName) { var propertyName = JsonConvert.DeserializeObject(reader.Value.ToString(), keyType); var value = serializer.Deserialize(reader, valueType); dictionary.Add(propertyName, value); } return dictionary; } } ``` 使用方法如下: ``` // 序列化 Dictionary<string, object> dic = new Dictionary<string, object>(); string json = JsonConvert.SerializeObject(dic, new MyDictionaryConverter()); // 反序列化 Dictionary<string, object> result = JsonConvert.DeserializeObject<Dictionary<string, object>>(json, new MyDictionaryConverter()); ``` 需要注意的是,需要在属性上添加 `[JsonConverter(typeof(MyDictionaryConverter))]` 特性来告诉 `Newtonsoft.Json` 使用上述自定义的 `MyDictionaryConverter` 来进行序列化和反序列化
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值