当在Unity游戏中需要加载和管理游戏数据,通常使用JSON文件是一种常见的方法。在本篇博客中,我们将深入探讨如何使用C#和Unity的JSON反序列化功能来实现这一目标。我们可以使用Unity的JsonUtility来反序列化JSON数据并将其映射到自定义的C#数据结构中。
首先,让我们来创建一些数据类,以便加载和管理游戏中的角色和武器数据。在这个示例中,我们将使用Player(角色)、Monster(怪物)和WeaponData(武器数据)这三种数据类型。
xml
{
"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序列化和反序列化
csharp
[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文件示例是一个包含多个玩家信息的数组。
csharp
[Serializable]
public class PlayerData
{
public List<Player> players = new List<Player>();
}
我们可以用一个玩家数据结构的数组去存储这个json文件,并
用
csharp
TextAsset textAsset = Managers.Resource.Load<TextAsset>($"Data/PlayerData");
PlayerData []players JsonUtility.FromJson<Loader>(textAsset.text);
去解析并且遍历它放到字典里,
当我们要解析的json特别多时 我们定义了一个泛型方法LoadJson,该方法负责加载JSON数据并将其反序列化为具体类型的字典。这个方法接受一个Loader类型,该类型必须实现ILoader接口。
csharp
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接口
cpp
public interface ILoader<Key, Value>
{
Dictionary<Key, Value> MakeDict();
}
我们让存储具有JSON数据结构的数组继承该接口
csharp
[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文件反序列化放在数组中
csharp
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();
}
代码如下
csharp
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数据并将其转化为字典对象。
csharp
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反序列化和数据管理有所帮助。如果你有任何问题或需要进一步的指导,请随时在评论中提问!