如何在Unity中读取JSON并转为DialogSequence对象数组?
解决Unity中Twine导出JSON的反序列化问题
核心问题拆解
你遇到的问题主要来自三个方面:
- DialogSequence类的定义问题:继承了
MonoBehaviour的类无法被JsonUtility直接序列化/反序列化,因为这类对象是Unity的组件实例,并非普通数据类。同时Sprite是Unity引用类型,不能直接序列化为字符串,需要改用路径存储。 - JSON结构与C#类不匹配:你的JSON外层是包含
Story数组的对象,而Story中每个元素是动态键(剧情标题)对应DialogSequence数组的结构,JsonUtility对这种动态键的支持很差。 - 反序列化调用错误:你直接用
JsonUtility.FromJson<DialogSequence[]>解析,但JSON根节点是对象而非数组,类型完全不匹配,导致报错。
具体解决方案
1. 重构DialogSequence数据类
先把它改成普通可序列化的数据类,替换Sprite为路径字符串:
[System.Serializable] public class DialogSequence { public string TextDialog; // 对话框文本 public string TextNameCharacter; // 显示的角色名 public string SpriteCharacterPath; // 角色图片路径(替代原Sprite) public string SpriteBackgroundPath; // 背景图片路径(替代原Sprite) public bool ChoiceMultiple; // 是否有多选项 public string[] TextChoice; // 按钮文本(最多4个) public string[] IndexChoice; // 下一场景的数组索引/键 }
后续在Unity中通过路径加载Sprite,比如用
Resources.Load<Sprite>(SpriteCharacterPath),注意图片要放在Resources文件夹下,或用Addressables管理。
2. 使用Newtonsoft.Json处理动态键(推荐)
Unity自带的JsonUtility对动态键(比如每个剧情的自定义标题)支持有限,建议用Newtonsoft.Json(Unity官方适配版本,可通过Package Manager安装),它能轻松解析这种结构。
步骤:
打开Unity Package Manager → 点击
+→ 选择Add package from git URL→ 输入com.unity.nuget.newtonsoft-json安装。解析代码示例:
using Newtonsoft.Json; using System.Collections.Generic; using UnityEngine; public class MainGame : MonoBehaviour { void Start() { // 假设jsonString是你的JSON内容 string jsonString = "..."; // 解析外层结构:Story是列表,每个元素是单键字典(键为剧情标题,值为DialogSequence列表) var storyData = JsonConvert.DeserializeObject<StoryContainer>(jsonString); // 遍历所有剧情节点 foreach (var chapter in storyData.Story) { // 取出章节标题和对应的DialogSequence列表 foreach (var kvp in chapter) { string chapterTitle = kvp.Key; List<DialogSequence> dialogs = kvp.Value; // 这里处理剧情逻辑,比如打印测试 Debug.Log($"章节:{chapterTitle},包含{dialogs.Count}段对话"); } } } } // 定义外层容器类 public class StoryContainer { public List<Dictionary<string, List<DialogSequence>>> Story { get; set; } }
3. 若坚持使用Unity自带JsonUtility(需调整JSON结构)
如果不想引入第三方库,需要修改JSON结构,把动态键改成固定属性名,比如:
{ "Story": [ { "ChapterTitle": "Title1", "Dialogs": [ { "TextDialog": "", "TextNameCharacter": "", "SpriteCharacterPath": "", "SpriteBackgroundPath": "", "ChoiceMultiple": false, "TextChoice": ["Next"], "IndexChoice": ["Title2"] } ] }, { "ChapterTitle": "Title2", "Dialogs": [...] } ] }
然后定义对应的C#类:
[System.Serializable] public class ChapterData { public string ChapterTitle; public DialogSequence[] Dialogs; } [System.Serializable] public class StoryContainer { public ChapterData[] Story; }
最后反序列化:
var storyContainer = JsonUtility.FromJson<StoryContainer>(jsonString); // 访问storyContainer.Story获取所有章节数据
补充说明
- 如果你无法修改Twine导出的JSON结构,强烈推荐使用Newtonsoft.Json,它能完美适配动态键场景,无需调整JSON。
- 加载Sprite时,确保路径正确:如果用
Resources.Load,路径要去掉文件扩展名和Resources前缀,比如图片在Resources/Sprites/Characters/Alice.png,路径就写Sprites/Characters/Alice。
内容的提问来源于stack exchange,提问作者Jean Mahmoud
相关产品推荐
相关产品推荐

