Unity中使用JsonSerializer提示因保护级别不可访问如何解决
问题描述
在独立.NET控制台项目中可正常运行的JsonSerializer序列化逻辑,迁移到Unity环境后运行失败。
用于测试的序列化实体类代码如下:
public class MyClass { public int level {get; set;} public float timeElapsed {get; set;} public string playerName {get; set;} }
序列化逻辑代码如下:
MyClass myObject = new MyClass(); myObject.level = 1; myObject.timeElapsed = 47.5f; myObject.playerName = "Dr Charles Francis"; Console.WriteLine(JsonSerializer.Serialize(myObject));
上述代码在Windows环境下通过dotnet run指令运行完全正常,但放入Unity脚本运行时抛出如下错误:
'JsonSerializer' is inaccessible due to its protection level
报错原因
出现该问题的核心原因是:
- 低版本Unity默认使用.NET Framework兼容API,没有内置公开访问权限的
System.Text.Json.JsonSerializer实现,编译器默认匹配到的是Unity引擎内部封装的非公开类,因此触发保护级别访问错误。 - 部分高版本Unity默认API兼容级别未开启.NET Core/.NET 6+支持,也无法正常访问公有的System.Text.Json相关类。
- 代码中直接使用
Console.WriteLine()也不符合Unity的日志输出规则,即使序列化逻辑正常,内容也无法显示在Unity编辑器控制台。
可行解决方案
根据项目实际需求选择以下任意一种方案即可:
- 方案1:使用Unity官方内置的Newtonsoft Json(推荐,兼容性最好)
Unity 2020及以上版本已经官方内置Json.NET(Newtonsoft.Json)作为默认JSON序列化方案,无需额外导入第三方包,只需要修改命名空间引用和序列化方法即可正常使用,示例代码如下:using UnityEngine; using Newtonsoft.Json; public class MyClass { public int level {get; set;} public float timeElapsed {get; set;} public string playerName {get; set;} } public class SerializeTest : MonoBehaviour { void Start() { MyClass myObject = new MyClass(); myObject.level = 1; myObject.timeElapsed = 47.5f; myObject.playerName = "Dr Charles Francis"; Debug.Log(JsonConvert.SerializeObject(myObject)); } } - 方案2:调整Unity配置以支持原生System.Text.Json
如果你使用Unity 2022.2及以上版本,且必须使用System.Text.Json下的JsonSerializer,可以按以下路径修改配置:
打开Edit > Project Settings > Player > Other Settings > Configuration面板,将Api Compatibility Level选项修改为.NET 6(或更高版本的.NET Core选项),等待脚本重新编译后,添加using System.Text.Json;命名空间引用即可正常调用JsonSerializer.Serialize()方法,注意将输出方法替换为Debug.Log()。 - 方案3:手动导入System.Text.Json包适配低版本Unity
如果使用2021及更早的低版本Unity,且不想替换序列化方案,可以通过NuGet下载对应.NET版本兼容的System.Text.Json正式dll文件,放入项目的Assets/Plugins目录下,等待脚本编译完成后即可正常访问公有的JsonSerializer类。
注意:所有在Unity编辑器中运行的日志输出都需要使用
Debug.Log()、Debug.LogWarning()、Debug.LogError()等Unity自带的日志方法,Console.WriteLine()的输出不会被Unity编辑器捕获显示。
内容的提问来源于stack exchange,提问作者aarelovich
相关产品推荐
相关产品推荐

