using System.Collections;
using System.Collections.Generic;
using UnityEngine;
string filename = "data.json";
string jsonString;
string path;
[System.Serializable]
public class LevelGrid
{
public string[] rows;
}
[System.Serializable]
public class Levels
{
public LevelGrid[] levels;
}
void LoadGrid()
{
// Load data
string path = Application.streamingAssetsPath + "/" + filename;
jsonString = File.ReadAllText(path);
var levelBricks = JsonUtility.FromJson<Levels>(jsonString);
// DOESNT WORK
Debug.Log(levelBricks.levels[0]);
}
Мой data.json:
{
"Levels": [
{"Level1": ["1,1,1,1,1", "1,1,1,1,1", "1,1,1,1,1"]},
{"Level2": ["1,1,1,1,1", "1,1,1,1,1", "1,0,1,0,1"]}
]
}
Что-то не так с int levelBricks, и из json ничего не загружается должным образом. Что я делаю неправильно? Debug.Log выдает ошибку, и если я использую только Debug.Log «levelBricks», все, что я получаю, это «Levels». Я хотел бы иметь доступ к массивам на Уровне 1 и Уровне 2.
Попробуйте использовать json.net вместо JsonUtility newtonsoft.com/json
OP использует Unity, насколько я знаю, JSON.NET недоступен в Unity. Кроме того, ошибка довольно очевидна. Ключи Level1 и Level2 динамические, классы C# этого не отражают ...
Не уверен в Unity, но вы можете выполнить десериализацию в JSON.Net с помощью этого класса public class Levels { public Dictionary<string, string[]>[] levels; }, чтобы это могло сработать.
@DavidG, это сработает? Levels - это массив объектов, использование словаря даст объект, а не массив объектов. По крайней мере, насколько мой опыт работы с Json.NET
Нет, словари не поддерживаются в библиотеке Json по умолчанию Unity docs.unity3d.com/Manual/script-Serialization.html прочтите примечание здесь
@maccettura Да, работает в JSON.Net, поймите! i.stack.imgur.com/BJdJq.png
@DavidG о, я пропустил обозначение массива в объекте Dictionary. Виноват! Я бы сказал, что это ответ, вы получите мой голос
@maccettura Да, неприятно, но работает. Не вижу причин, по которым вы не можете добавить JSON.Net в Unity, теперь он нацелен на Net Standard, поэтому должен работать где угодно.
@DavidG Я думаю, это потому, что Unity построен на Mono. Я попытался исследовать его, и похоже, что все пакеты Json.NET, доступные для него, являются копиями, а не сделаны Newtonsoft. Я никогда не использовал Unity, так что я далеко не разбираюсь в этом предмете.
@maccettura То же самое и здесь. На веб-сайте JSON.Net говорится, что он работает под Mono, хотя это должен быть случай импорта DLL.
Сказав это, если бы я использовал JSON.Net, я бы, вероятно, использовал специальный преобразователь для динамического свойства.
@DavidG Слишком много причин. Дело не только в работе в Windows. Unity является мультиплатформенным, и на таких платформах, как iOS, он не работает из-за AOT. Кроме того, Unity недавно добавила поддержку сети 4.5, что является минимальным требованием для Json.Net. Только те, у кого установлена последняя версия Unity, могут использовать это, но проблемы с AOT все еще остаются. К счастью, есть разветвленная версия Json.Net, созданная для Unity, чтобы решить эти проблемы. здесь
Вам действительно стоит взглянуть на мой обновленный ответ. Я отредактировал только через две минуты после того, как сказал, что основная проблема была в переменной. С моим ответом вы сможете делать все с помощью базовой библиотеки единства json.
@Programmer Этой библиотеке уже 2 года. JSON.Net теперь нацелен на .NET Standard 1, 1.3 и 2.0 и является полностью переносимым.
Старость не имеет значения. Он по-прежнему работает и используется многими пользователями Unity. Я также слышал, что JSON.Net был обновлен для поддержки более низких версий .NET, но я не пробовал их протестировать, и простая поддержка этой версии не означает, что проблемы с сбоями, вызванные AOT или неподдерживаемыми функциями, теперь решены.
@Programmer Да, я хорошо осведомлен об этом, но сейчас я использую JSON.Net на всех платформах (Windows, .NET Core, Linux, Android, iOS и т. д.), И он отлично работает. Я не вижу причин, по которым это не сработает и в Unity
Я читаю, мне нужно просто обернуть массив [System.Serializable] публичный класс BrickGrid {[System.Serializable] публичный класс LevelGrid {публичная строка [] уровни; } общедоступные уровни LevelGrid []; }
@Ranch Как я уже сказал в своем ответе, вы не сможете сериализовать 2 массива строк, если ваш класс имеет только 1 массив строк. Просто попробуйте, и вы узнаете, что мой ответ правильный, если вы хотите использовать библиотеку Unity по умолчанию (чем вы можете ее принять). Кроме того, да, обертка объекта правильная





Основная проблема заключается в том, что переменные вашего класса должны использовать то же имя, что и ваш json. пример: публичная строка [] строк;
должно быть публичная строка [] Уровни;
РЕДАКТИРОВАТЬ. вам нужен сериализуемый класс с
[SerializeField] ClassForLevel12[] levels;
public ClassName() {
}
public ClassName(ClassForLevel12[] levels) {
this.levels = levels;
}
и геттер / сеттер
public static ClassName SaveFromString(string
jsonString) {
return JsonUtility.FromJson<ClassName>(jsonString);
}
public string SaveToString() {
return JsonUtility.ToJson(this);
}
и сериализуемый класс ClassForLevel12 с 2
public string[] level1;
public string[] level2;
(и все как у другого класса).
Окончательное РЕДАКТИРОВАНИЕ. Хорошо, это то, что вам нужно, просто скопируйте, вставьте и поймите:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class MyLevels{
[SerializeField] List<LevelGrid> levels;
public MyLevels(){}
public MyLevels(List<LevelGrid> levels){
this.levels = levels;
}
public List<LevelGrid> Levels{
get { return levels; }
set { levels = value; }
}
//from a jsonstring to an object
public static MyLevels SaveFromString(string jsonString){
return JsonUtility.FromJson<MyLevels>(jsonString);
}
//object to json
public string SaveToString(){
return JsonUtility.ToJson(this);
}
}
Второй класс
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class LevelGrid{
[SerializeField] string[] level1;
[SerializeField] string[] level2;
public LevelGrid() {
}
public LevelGrid(string[] level1, string[] level2) {
this.level1 = level1;
this.level2 = level2;
}
public string[] Level1{
get { return level1; }
set { level1 = value; }
}
public string[] Level2{
get { return level2; }
set { level2 = value; }
}
//from a jsonstring to an object
public static LevelGrid SaveFromString(string jsonString) {
return JsonUtility.FromJson<LevelGrid>(jsonString);
}
//object to json
public string SaveToString() {
return JsonUtility.ToJson(this);
}
}
Теперь ты можешь просто вызвать
string jsonString = "{ \"levels\": [ {\"level1\": [\"1,1,1,1,1\", \"1,1,1,1,1\", \"1,1,1,1,1\"]},{\"level2\":[\"1,1,1,1,1\", \"1,1,1,1,1\", \"1,0,1,0,1\"]}]}";
MyLevels levelBricks = MyLevels.SaveFromString(jsonString);
Debug.Log(levelBricks.Levels[0].Level1[0]);
Класс Levels имеет свойство levels. Изменение строк на Levels не исправит это
ему все еще не хватает level1 и level2. Также переменная строк неверна как верхняя сериализуемая
Что происходит, когда json содержит level3, level4? Видишь ли, это неправильно
json должен отражать данные в классе. Библиотека Unity получает только базовую поддержку примитивных типов и нескольких сложных типов (например, List). Я уверен, что есть много хороших и лучших библиотек, которые лучше, чем по умолчанию Unity, но если вам нужно использовать библиотеку по умолчанию Unity3d, это правильный ответ. docs.unity3d.com/Manual/script-Serialization.html это документы
Я не уверен, что понимаю этот ответ. Не могли бы вы написать его точно так же, как Id-код? @Mah
@Rach, теперь должно быть ясно. Вам просто нужно скопировать и вставить. Если есть что-то, чего вы не поняли, просто спросите. теперь код должен быть действительно легко читаемым.
Также ... вы можете использовать [SerializeField] вместо общедоступных, как в моем первом примере для переменных, если вы не хотите, чтобы они были общедоступными (в конце концов, вам нужен геттер / сеттер)
@Rach Хорошо, я попробовал прямо сейчас. Просто скопировать и вставить не работает, потому что есть проблема с именованием ... Я редактирую ответ прямо сейчас с полным рабочим и проверенным кодом.
Debug.Log (уровень Bricks.Level1] .Level2 [0]); Уровень 2 не работает @Mah
@Rach, ты можешь поблагодарить меня, приняв мой ответ и проголосовав за. чтобы все знали, что это правильный ответ, чтобы посмотреть на
Что такое
JsonUtility.FromJson?