ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Unity 2022一键安装Newtonsoft.Json:告别手动DLL,拥抱UPM包管理

Unity 2022一键安装Newtonsoft.Json:告别手动DLL,拥抱UPM包管理 做Unity开发这几年JSON序列化这块我基本只用Newtonsoft.Json。以前每开一个新项目都得去官网下DLL、丢进Plugins文件夹、手动处理依赖麻烦不说还容易在版本升级时踩坑。Unity 2022版之后Newtonsoft.Json正式以官方包的形式进了Package Manager安装流程被压缩成了“搜索、点击、等待”三个动作这一键体验确实省了一大堆事。这篇教程就围绕Unity 2022里的Package Manager安装流程把具体操作、版本选择、程序集引用和常见报错全部过一遍适合正在用Unity 2022做存档、联网同步、配置读取之类功能的开发者参考新手也能直接照做。1. 从手动DLL到UPM包一键安装背后的变化1.1 老方案到底麻烦在哪在Package Manager能直接搜到Newtonsoft.Json之前Unity项目接入这个库通常有两条路一是去Newtonsoft官网下载对应版本的dll然后手动扔到Assets/Plugins目录下二是在Asset Store里装第三方打包好的插件。这两种方式本身能用但问题不少。最典型的是版本管理混乱同一个团队不同人可能拿着不同版本的dll合并代码后经常出现“我这个接口怎么没有”的尴尬情况。另外DLL文件不会跟着包管理工具走换电脑拉代码后经常忘记带上Plugins目录一编译就是一堆找不到命名空间的报错。还有一类更隐蔽的问题某些插件自身会捆绑一份Newtonsoft.Json.dll比如一些云服务SDK、热更新框架、网络库它们各自带着一个版本。一旦项目里出现两份dll编译时会直接爆CS0433“类型同时存在于两个程序集中”的错误。这种问题排查起来非常难受因为你不知道是哪个包带进来的只能一个一个翻文件夹。所以老方案的核心痛点不是“能不能用”而是“维护成本高”。尤其是项目变大、多人协作以后手动管理dll几乎等于埋雷。1.2 Unity官方UPM包到底做了什么Unity官方后来出的这个包包名是com.unity.nuget.newtonsoft-json意思是把NuGet上的Newtonsoft.Json包装成了Unity标准的UPM包。它解决的正是上面说的版本管理和依赖冲突问题。装好之后Unity会在Packages/manifest.json里自动记录依赖和版本号整个项目只要同步manifest文件其他人拉代码后Unity会自动把对应版本的包拉下来不用再手动传文件。这个包本质上是把Newtonsoft.Json的程序集放进了UPM的包管理体系里。它提供的是一个编译好的运行时程序集命名空间仍然是大家熟悉的Newtonsoft.Json。所以老项目里用到的JsonConvert、JObject、JsonSerializerSettings这些类在新方案里完全不需要改代码直接把旧的dll删掉换装UPM包就能平滑过渡。有一点要注意这个包不是Unity自己重写的JSON库它就是把官方Newtonsoft.Json拿过来做了一层包管理封装。所以Newtonsoft.Json原版的各种高级特性比如LINQ to JSON、自定义JsonConverter、JsonProperty特性、骆驼命名策略等全都保留。你在网上搜到的Newtonsoft.Json用法依然全部适用。1.3 为什么2022版是关键节点虽然这个UPM包在2020年左右就出现了但Unity 2022.2之后的体验才算真正“一键”。原因很简单从2022.2开始Unity Registry默认收录了这个包你不需要手动添加第三方源也不需要去GitHub找安装入口直接在Package Manager的搜索框里输入newtonsoft就能看到它。这个默认收录非常关键意味着官方替你搞定了一切兼容性测试和版本筛选你在界面上能看到的版本都是验证过能在当前Unity版本跑的。换句话说2022版里你只需要做两件事打开Package Manager搜索并点击Install。其余的事情全部由Unity处理。这也是我写这篇教程的直接原因现在的安装流程已经简单到不应该还有人去手动塞DLL了。2. 一键安装实操最新Package Manager教程2.1 打开Package Manager并切换到Unity Registry第一步在Unity编辑器顶部菜单栏选择Window - Package Manager打开包管理窗口。这一步没什么好说的重点在窗口左上角。默认情况下Package Manager的顶部有一个下拉框显示当前浏览的包来源。这里有个非常常见的坑如果你的项目配置过其他包源比如Scoped Registry或者企业内部源这个下拉框可能会停在My Registries在这个来源下搜newtonsoft大概率是搜不到官方包的因为Unity官方包不在私人源里。正确操作是把这个下拉框切换到Unity Registry这是Unity官方包源的入口所有内置和官方维护的包都在这里面。切换之后下方列表会自动加载官方源里当前Unity版本支持的所有包。首次加载可能需要一点时间尤其网络状态一般的时候列表会出现一段空白等几秒或点一下刷新按钮就好。2.2 一键搜索并执行安装在Package Manager窗口右上角的搜索框里输入newtonsoft不需要带连字符搜索结果里会出现一个名为Newtonsoft Json的包发布方一栏标注的是Unity Technologies。点选这个包右侧会显示包的详细信息包括当前版本、发布时间、发布说明等。确认没问题后点击右下角的Install按钮Unity就开始自动下载并安装。整个过程在进度条走完后按钮会变成Update或Remove说明包已经成功安装。这一步没有任何复杂的选项也不需要选目录、配环境变量这就是“一键安装”的全部内容。装完以后Unity会自动完成程序集编译。回到你的脚本里在文件头部加一行using Newtonsoft.Json;如果编辑器右上角没有飘红就说明环境已经通了。2.3 搜索不到时的替代入口Add package by name虽然Unity 2022.2的Registry里已经收录了这个包但偶尔也会出现搜索不到的情况。原因有很多比如Unity编辑器版本较旧、缓存异常或者项目手动改过Registry配置。这时候有一个很实用的替代入口点击Package Manager窗口左上角的号选择Add package by name...在弹出的输入框里填入包名com.unity.nuget.newtonsoft-json版本号可以留空表示用最新版本也可以指定比如3.2.1点击Add就会开始安装。这个方法等同于手工写入manifest.json效果和搜索安装完全一样。如果你连Add package by name都觉得麻烦也可以直接打开项目根目录下的Packages/manifest.json文件在dependencies节点里加一行com.unity.nuget.newtonsoft-json: 3.2.1保存后切回Unity编辑器它会自动检测到manifest变化并开始解析依赖速度上可能比界面操作更快一些。这个逻辑对任何UPM包都通用属于Unity包管理的基本功。2.4 版本选择与升级回退策略Package Manager安装时默认选择的版本通常是当前Unity版本下官方推荐的最新版。但如果你的项目不需要最新特性或者担心新版本有其他兼容性问题完全可以手动指定版本。点击包名旁边的版本下拉框里面会列出当前Unity版本支持安装的所有历史版本选一个点Install即可。这里我整理了一下官方包版本和底层Newtonsoft.Json版本的对应关系方便你在网上查资料时对上号UPM包版本底层Newtonsoft.Json版本发布时间线1.1.012.0.1较早适合老项目2.0.012.0.3中早期大量旧教程对应版本3.0.013.0.1Unity 2022.1前后3.2.113.0.3较新推荐优先使用比较关键的一点是Unity Registry会自动过滤掉当前工程Unity版本不兼容的包版本。比如你在Unity 2022.2里搜索看到的版本列表和你在Unity 2020里看到的可能完全不一样。所以如果你在低版本Unity里想用这个包却搜不到新版看下可用的旧版版本号就好挑一个时间线匹配的即可。版本回退也是一样的逻辑在版本下拉框里选中旧版本点Update旁边的切换按钮Unity会自动处理降级。提示尽量不要在项目推进到一半时频繁升降这个包的版本。虽然Newtonsoft.Json接口非常稳定但主版本升级之间偶尔有一些序列化行为的微调比如日期格式的默认处理方式。验证过没问题的版本就锁定它。3. 安装后的配置与代码验证3.1 怎么确认安装真的成功安装完成后第一件事是确认包确实进入了项目。看Packages/manifest.json里面应该有com.unity.nuget.newtonsoft-json: 3.2.1这行依赖就是安装成功的直接证据。同时在Unity编辑器的Project窗口里展开Packages目录会看到多出一个Newtonsoft Json条目点开里面有package.json、Newtonsoft.Json.dll等文件。看到这个就说明包已经放进了当前工程并且会被Unity自动引用。另一个更直观的判断方式是直接修改一段脚本测试编译。比如随便打开一个现有的C#脚本在最顶部加using Newtonsoft.Json;然后保存并切回Unity窗口。如果没有任何编译报错说明程序集已经成功被项目引用可以正式使用了。如果这一步飘红报的是CS0234: 命名空间“Newtonsoft”中不存在类型或命名空间名“Json”那么大概率是项目里的程序集引用配置有问题这个问题在下面程序集定义小节专门说。3.2 写一个最小用例验证序列化确认引用没问题后我建议立刻写一个最小测试脚本把序列化和反序列化各跑一遍排除环境问题。新建一个C#脚本写入如下内容using Newtonsoft.Json; using System; using System.Collections.Generic; using UnityEngine; public class JsonQuickTest : MonoBehaviour { [Serializable] public class PlayerData { public string playerName; public int level; public Listint itemIds; public Dictionarystring, float stats; [JsonProperty(create_time)] public DateTime CreateTime { get; set; } } void Start() { var data new PlayerData { playerName test, level 12, itemIds new Listint { 1, 2, 3 }, stats new Dictionarystring, float { [hp] 100f, [atk] 30f }, CreateTime DateTime.Now }; string json JsonConvert.SerializeObject(data, Formatting.Indented); Debug.Log(json); var restored JsonConvert.DeserializeObjectPlayerData(json); Debug.Log(${restored.playerName}, level:{restored.level}); } }把脚本挂到一个场景物体上运行Console里应该能打印出格式化好的JSON字符串并且反序列化出的对象字段值正确。这个用例重点覆盖了列表、字典、属性和自定义字段名基本代表了日常开发的典型需求。跑通了就说明安装环境完全正常。3.3 自定义程序集怎么引用Newtonsoft.Json如果你的项目还停留在默认的Assembly-CSharp程序集上面这些操作已经足够了不需要额外配置。但很多Unity项目到了中后期会引入程序集定义文件asmdef来组织模块比如把核心逻辑、UI、工具类拆成独立程序集以加快编译速度、明确依赖关系。有asmdef的项目会踩一个典型的坑包管理器里明明已经安装了Newtonsoft.Json脚本里using Newtonsoft.Json;也写了编译器照样报错找不到命名空间。原因在于asmdef默认只会引用它显式声明或自动引用的程序集UPM包里的Newtonsoft.Json.dll不会被默认链接进每个自定义程序集。解决办法也简单。找到你的asmdef文件双击打开Inspector面板在Assembly Definition References列表里点击号然后在下拉列表中找到Newtonsoft.Json选中保存。注意这里选的是Newtonsoft.Json这个程序集引用不是其他带版本后缀的条目。保存后重新编译命名空间就能正常解析了。如果你的asmdef在Inspector里开了Auto Referenced选项那么它会自动引用所有开启了自动引用标记的包程序集可能不需要手动添加。但依赖关系这种东西显式声明远比隐式规则靠谱遇到问题优先排查asmdef引用绝对没错。3.4 和JsonUtility的取舍安装好Newtonsoft.Json之后有人会问一个问题Unity自己不是有个JsonUtility吗为什么还要用Newtonsoft.Json我的看法是两者定位不同。JsonUtility更轻量对Unity内置类型和MonoBehaviour字段的支持是原生级优化性能也好适合序列化简单的存档数据。但它的限制非常明显不直接支持Dictionary不能通过特性轻松改字段名对多态和继承的支持非常弱处理复杂嵌套结构时写起来很累。Newtonsoft.Json的优势恰好能补上这些短板。比如游戏里常见的角色属性表用一个Dictionarystring, float就能存干净的键值对JsonUtility根本序列化不了再比如服务器下发的数据字段是下划线命名而C#代码规范是驼峰命名用[JsonProperty(create_time)]就能平滑映射。这些看起来很小的能力在真实项目里往往就是决定“这个库够不够用”的分水岭。我的建议是简单存档用JsonUtility一旦数据结构开始出现字典、多态、自定义命名或者服务器对接需求直接换Newtonsoft.Json不要混着用。4. 常见问题与避坑手册4.1 CS0433类型重复定义旧DLL与UPM包冲突这是从老方案切换到UPM方案时最容易踩的坑。项目里原本在Plugins目录或某个插件里已经放了一份Newtonsoft.Json.dll现在又通过Package Manager装了一份编译时编译器会发现两个程序集里都有Newtonsoft.Json.JsonConvert等类型直接报CS0433。解决方案是先找到旧的那份dll删掉然后清理一下编译缓存。搜索的时候注意很多插件不会把dll直接放在根目录的Plugins文件夹而是放在自己的插件包目录里比如Assets/ThirdParty/SomeSDK/Plugins/Newtonsoft.Json.dll。可以先用Unity编辑器左上角的搜索功能搜文件名Newtonsoft.Json.dll把整个工程里的重复dll都列出来再逐一判断哪些是必须保留的。注意如果冲突来源是某个第三方SDK强制捆绑的版本而且这个SDK没有开放配置选项删掉它的dll可能会让SDK出问题。这种情况下建议先联系插件作者确认支持方案而不是硬删。4.2 IL2CPP构建报错用link.xml解决AOT裁剪Unity的项目如果开启了IL2CPP构建比如发布到iOS、AndroidIL2CPP后端或者WebGL会遇到一类AOT裁剪问题。Newtonsoft.Json内部大量使用反射尤其是通过字符串类型名创建对象、用反射读取属性值这些操作在IL2CPP的AOT裁剪机制下相关类型或方法可能在构建时被当成“没用过”而被剔除导致运行时抛出MissingMethodException、TypeInitializationException或者SerializationException。这类问题很有迷惑性因为编辑器里跑得完全正常一打包到真机就崩。常规解法是添加link.xml文件告诉IL2CPP哪些程序集要完整保留。在Assets目录下新建一个link.xml文件写入linker assembly fullnameNewtonsoft.Json preserveall / /linkerUnity构建时会读取这个文件并完整保留Newtonsoft.Json程序集中的所有类型和成员。代价是包体体积会变大一些但对于大多数游戏项目来说完全在可接受范围内。如果你用的是assemble definition并有多个平台变体也可以把link.xml放到特定文件夹下按平台生效但常规情况下放Assets根目录就够了。我实际测下来很多网上说的“iOS崩溃”案例加了这个link.xml之后都能解决。如果你项目里还用到了自定义JsonConverter建议在link.xml里连你的程序集一起保留避免自定义转换器里的逻辑被裁剪掉。4.3 序列化结果和预期不一致JsonProperty与NullValueHandling安装了包之后序列化结果和预期不一致是另一类高频问题。最常见的是字段被丢掉了比如某个对象序列化出来少了一个属性或者多了一个不想要的字段。前者通常是因为字段为null而序列化设置里默认会输出null值如果你没看到null字段可能是设置了NullValueHandling.Ignore。后者则常见于用自动属性Property且没有加特性控制默认情况下Newtonsoft.Json会尽量序列化所有公开的getter属性。控制输出格式的标准做法是使用JsonSerializerSettingsvar settings new JsonSerializerSettings { NullValueHandling NullValueHandling.Ignore, DefaultValueHandling DefaultValueHandling.Ignore, Formatting Formatting.None }; string json JsonConvert.SerializeObject(data, settings);还有一个值得留意的问题日期的格式。Newtonsoft.Json默认用ISO 8601格式处理DateTime不少服务器端或者旧系统的时间格式是/Date(1234567890)/或者自定义格式直接反序列化很可能报错或拿到错误时间。标准做法是在设置里指定日期格式更稳妥的方式是写一个自定义JsonConverter。这个问题在对接老项目接口时几乎必踩一次先有个心理预期。4.4 网络与缓存导致的安装失败Package Manager本身是个联网功能如果网络状况不好或者处于一个对网络访问有管控的开发环境里安装时可能卡在进度条不动或者直接报Failed to resolve。这种问题第一反应是检查网络连通性但很多人忽略了一点先看一眼是不是有本地缓存残留。Unity的包缓存目录在Library/PackageCache下如果之前删包没删干净可能留下损坏的缓存这时删掉缓存文件夹让Unity重新拉取一次往往就通了。提示如果项目要求离线开发可以在一台联网机器上把包下载到本地然后将整个包目录放到内网环境通过Add package from disk的方式安装。这种方式适合内网团队能极大减少安装失败概率。4.5 问题速查表现象可能原因快速解决搜索框搜不到NewtonsoftPackage Manager停留在My Registries切换下拉框到Unity Registry编译报CS0234找不到命名空间缺少using或asmdef未引用加using Newtonsoft.Json;检查asmdef引用编译报CS0433类型重复项目里存在旧的Newtonsoft.Json.dll删旧DLL清理缓存编辑器正常iOS/Android真机崩溃IL2CPP裁剪掉了反射用的类型在Assets下添加link.xml并保留Newtonsoft.Json序列化丢了Null字段或多余字段没配置JsonSerializerSettings显式设置NullValueHandling等参数日期格式反序列化报错ISO 8601与目标格式不兼容自定义DateTime转换器或设置DateFormatStringInstall卡在进度条网络问题或本地缓存损坏检查网络删除Library/PackageCache后重试升级包后某些行为变化主版本序列化细节微调查看release notes必要时回退版本5. 一点个人经验工具链这东西只有真正在项目里被坑过才知道省心有多重要。我在2022版发布后用这个一键安装流程替换了几乎全部老项目的DLL方案最大的感受是团队协作时再也没有人因为一份dll文件没提交而编译失败了。最后分享一个小技巧。很多项目会同时用Newtonsoft.Json和JsonUtility如果你打算长期用Newtonsoft.Json建议在项目里自己封装一个JsonHelper静态类统一封装SerializeObject和DeserializeObject顺手把Formatting.Indented、NullValueHandling.Ignore这些常用参数固化进去。这样将来换版本、调配置的时候只改一个文件不用满项目翻JsonConvert的调用点。这一点看起来不起眼但项目越大越值钱。
返回列表