如何解决Unity两个包中Google.Protobuf.DLL版本冲突问题
Unity 同名预编译DLL(Google.Protobuf多版本)冲突修复方案
你之前重命名DLL磁盘文件、修改asmdef引用仍未解决问题的核心原因:*.NET运行时识别程序集不靠磁盘文件名,而是靠程序集内嵌清单里的完整标识(包含程序集名、版本号、公钥令牌、文化信息),仅修改磁盘文件名不会改变程序集内部身份,Unity加载时仍会识别到两个标识完全重复的程序集触发报错。
以下方案按可维护性从高到低排序,可根据自身项目场景选择:
方案1:统一Protobuf版本 + 绑定重定向(优先推荐,维护成本最低)
Google.Protobuf 3.x全系列做了向后兼容设计,高版本API可覆盖低版本调用需求,绝大多数场景不需要保留双版本:
- 保留版本号更高的3.15.0.0版本DLL,删除3.8.0.0版本的DLL文件
- 在项目Assets目录下新建和DLL同目录的
Google.Protobuf.dll.config配置文件,写入程序集绑定重定向规则,让原本依赖3.8.0版本的代码自动重定向到3.15.0版本加载:
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Google.Protobuf" publicKeyToken="a7d26565bac4d604" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-3.15.0.0" newVersion="3.15.0.0"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
- 回到Unity编辑器触发全量重编译,验证两个功能包的核心流程即可,该方案不需要修改第三方包源码,后续升级包版本也不会有额外维护成本。
方案2:修改程序集内部标识实现双版本共存(适合版本不兼容、必须保留双版本的场景)
如果两个包依赖的Protobuf版本存在API Breaking Change,无法统一版本,按以下步骤操作:
- 准备IL修改工具:可选用ILRepack或者Mono.Cecil,均为.NET生态免费的程序集处理工具
- 选择其中一个版本的DLL(建议选版本更低的3.8.0.0),用工具修改程序集内嵌的完整标识:将程序集名从
Google.Protobuf修改为自定义名称(比如Google.Protobuf.V38),同时同步修改该DLL内部所有对自身程序集的引用,避免内部调用找不到类型 - 将你Fork的功能包中原本的3.8.0版本DLL替换为修改完标识的DLL文件
- 打开该功能包对应的
.asmdef(Assembly Definition)文件,将原有的Google.Protobuf引用替换为你修改后新名称的程序集引用 - 另一个功能包依赖的3.15.0版本DLL保持默认名称和标识不做修改,避免多余改动
- 触发Unity重编译即可,此时两个DLL的程序集完整标识完全不同,不会触发冲突,两个功能包会分别加载对应版本的依赖。
方案3:平台/场景约束隔离(适合两个包不会同时运行的场景)
如果两个功能包的生效范围完全不重叠(比如一个是仅在Unity Editor下运行的工具包,一个是仅在目标构建平台运行的运行时包),不需要修改DLL本身,直接通过导入配置隔离即可:
- 选中3.8.0版本的DLL,在Inspector面板的Platform Settings板块,取消勾选不需要生效的平台,仅保留该DLL所属包需要运行的目标平台
- 选中3.15.0版本的DLL,在Platform Settings板块配置和前者完全互斥的生效平台,保证任意时刻只有一个DLL会被Unity加载
- 该方案操作成本最低,但仅适用于两个包运行范围完全不重叠的场景,不适合运行时同时需要两个包功能的项目。
注意:不要尝试靠把两个DLL放在不同文件夹路径下做隔离,Unity默认会扫描项目目录下所有的DLL文件,只要程序集内部标识重复,无论路径在哪都会触发冲突报错。
内容的提问来源于stack exchange,提问作者jade
相关产品推荐
相关产品推荐

