【问题标题】:MonoGame - Load JSON Through the content pipelineMonoGame - 通过内容管道加载 JSON
【发布时间】:2019-04-03 07:37:07
【问题描述】:

我正在创建一个 RPG 游戏,我需要使用 Tiled 加载地图。我有 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";
        }
    }
}

有没有更好的方法来存储平铺地图元数据?还是有更好的方法通过管道导入它?还是我的内容导入器有问题?

【问题讨论】:

  • 与崩溃相关的错误信息是什么?
  • 您可以将 Tiled 中的自定义属性添加到地图、图层,甚至添加到 Tiled 中的每个对象。我使用 TiledSharp 而不是 Monogame.Extended 但我确信它也支持自定义道具的使用。
  • System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information 那是来自内容管道的错误消息

标签: c# json monogame


【解决方案1】:

错误是由dynamic 类型引起的。管道要求所有类型都可以通过反射进行解析和实例化。

Generic 集合有一个辅助解析器,用于对 Generic 中的每个类型进行序列化和反序列化。行Dictionary&lt;string, dynamic&gt; 有两种类型和与System.Collections.Generic.DictionarySystem.Stringdynamic 关联的未知类型。 dynamic 没有提示要使用什么类型,并且无法解析导致错误。

简单的解决方案是将数据存储为 json 字符串(您现在已经在这样做了,除了您尝试存储它的类型是 dynamic)并在 @987654329 之后将 String 反序列化到其对象中@已返回数据。

换句话说,使用Dictionary&lt;string, string&gt; 作为内容处理器类型。


更简单的解决方案是将JSON 文件复制到输出目录。构建动作“copy if newer”并使用 System.IO.File 读取它并使用 JSON.NET 将其反序列化为 Game1 的 Initialize 方法中的对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多