МоноГейм — Загрузка JSON через конвейер содержимого

#c# #json #monogame

#c# #json #моногейм

Вопрос:

Я создаю RPG-игру, и мне нужно загрузить карты с помощью Tiled. У меня закрыта фрагментированная часть (я использую MonoGame.Extended ). Но мне нужны дополнительные данные о карте. Мой план состоит в том, чтобы использовать файл JSON, который содержит необходимую информацию. Тем не менее, я хотел бы использовать его через конвейер содержимого, поскольку он напрямую связан с картами листов.

Я попытался использовать пользовательское расширение конвейера контента. Он использовался JSON.Net для десериализации файла JSON в Dictionary<string, dynamic> . Однако, когда я компилировал DLL-файл и пытался ссылаться на него в инструменте конвейера, инструмент конвейера всегда выходил из строя.

Импортер контента:

 using System;
using System.Collections.Generic;
using System.IO;

using Microsoft.Xna.Framework.Content.Pipeline;

using Newtonsoft.Json;

namespace JsonExtension
{

    [ContentImporter(".json", DefaultProcessor = "JsonProcessor")]
    public class JsonImporter : ContentImporter<Dictionary<string, dynamic>>
    {

        public override Dictionary<string, dynamic> Import(string filename, ContentImporterContext context)
        {
            context.Logger.LogMessage("Importing JSON file: {0}", filename);

            using (var streamReader = new StreamReader(filename))
            {
                JsonSerializer serializer = new JsonSerializer();
                return (Dictionary<string, dynamic>)serializer.Deserialize(streamReader, typeof(Dictionary<string, dynamic>));
            }
        }

    }

}
  

Обработчик содержимого:

 using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework.Content.Pipeline;

namespace JsonExtension
{
    [ContentProcessor]
    public class JsonProcessor : ContentProcessor<Dictionary<string, dynamic>, Dictionary<string, dynamic>>
    {
        public override Dictionary<string, dynamic> Process(Dictionary<string, dynamic> input, ContentProcessorContext context)
        {
            context.Logger.LogMessage("Processing JSON");

            return input;
        }
    }
}
  

Средство записи типов содержимого:

 using System;
using System.Collections.Generic;
using System.IO;

using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;

using Newtonsoft.Json;

namespace JsonExtension
{
    [ContentTypeWriter]
    class JsonTypeWriter : ContentTypeWriter<Dictionary<string, dynamic>>
    {
        protected override void Write(ContentWriter output, Dictionary<string, dynamic> value)
        {
            output.Write(JsonConvert.SerializeObject(value));
        }

        public override string GetRuntimeType(TargetPlatform targetPlatform)
        {
            return typeof(Dictionary<string, dynamic>).AssemblyQualifiedName;
        }

        public override string GetRuntimeReader(TargetPlatform targetPlatform)
        {
            return "JsonExtension.JsonReader";
        }
    }
}

  

Есть ли лучший способ хранить метаданные плиточной карты? Или есть лучший способ импортировать его через конвейер? Или я делаю что-то не так с моим импортером контента?

Комментарии:

1. Какое сообщение об ошибке связано с аварийным завершением работы?

2. Вы можете добавлять пользовательские свойства в Tiled к карте, слоям и даже к каждому объекту, размещенному в Tiled. Я использую TiledSharp вместо Monogame. Расширенный, но я уверен, что он также поддерживает использование пользовательских реквизитов.

3. System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information Это сообщение об ошибке из конвейера содержимого

Ответ №1:

Ошибка связана с dynamic типом. Конвейер требует, чтобы все типы разрешались и создавались посредством отражения.

Для универсальных коллекций существует вторичный преобразователь для сериализации и десериализации каждого типа в универсальном. Строка Dictionary<string, dynamic> имеет два типа и и связанный с ними непознаваемый тип System.Collections.Generic.Dictionary , System.String и dynamic . dynamic Не содержит подсказок относительно того, какой тип использовать, и не может быть разрешен, что приводит к ошибке.

Простое решение состоит в том, чтобы сохранить данные в виде строки json (что вы уже делаете сейчас, за исключением того, что тип, в котором вы пытаетесь их сохранить, является dynamic ) и десериализовать String в свой объект после того, как Content.Load вернет данные.

Другими словами, использовать Dictionary<string, string> в качестве типа процессора содержимого.


Более простым решением было бы скопировать JSON файл в выходной каталог. Создайте действие «копировать, если новее» и используйте System.IO.File, чтобы прочитать его и JSON.NET десериализовать в объект в Initialize методе Game1.