介绍
Unity 编辑器第一次 Play 时没问题,第二次 Play 时偶尔会输出错误。
问题一旦发生后续改动代码就会发现 Unity 编译完成后却不生效,只能重启才生效,并且 Rider 无法进行调试。
每次改一点代码都需要重启 Unity 后进行调试,而且只有第一次运行正常,这实在让人崩溃。
环境
- Unity 2019.4.32f1
- Unity 2022.3.46f1
- Rider 2023.1
- Rider 2024.3
Console
Unity 内部控制台会输出以下错误:
1
2
3
4
5
6
7
8
9
|
Error: Could not load signature of DG.DOTweenEditor.ASMDEFManager:ValidateProASMDEFReferences due to: Could not load file or assembly 'DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type:<unknown type> member:(null) signature:<none>
Error: Could not load signature of DG.Tweening.DOTweenModuleAudio:DOFade due to: Could not load file or assembly 'DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type:<unknown type> member:(null) signature:<none>
Unloading broken assembly Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.dll, this assembly can cause crashes in the runtime
Unloading broken assembly Assets/Editor/UwaProjScan.dll, this assembly can cause crashes in the runtime
Unloading broken assembly Library/ScriptAssemblies/Demigiant.dll, this assembly can cause crashes in the runtime
|
Editor.log
Unity 编辑器的日志文件有可能会输出更多的信息,因此也需要查看:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<RI> Initialized touch support.
Reloading assemblies for play mode.
Begin MonoManager ReloadAssembly
Error: Could not load signature of DG.DOTweenEditor.ASMDEFManager:ValidateProASMDEFReferences due to: Could not load file or assembly 'DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type:<unknown type> member:(null) signature:<none>
(Filename: C:\buildslave\unity\build\Runtime/Mono/MonoAttributeHelpers.cpp Line: 363)
Error: Could not load signature of DG.Tweening.DOTweenModuleAudio:DOFade due to: Could not load file or assembly 'DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type:<unknown type> member:(null) signature:<none>
(Filename: C:\buildslave\unity\build\Runtime/Mono/MonoAttributeHelpers.cpp Line: 363)
Could not load signature of DG.DOTweenEditor.UI.DOTweenUtilityWindow:GetDOTweenSettings due to: Could not load file or assembly 'DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type:<unknown type> member:(null) signature:<none>
Could not load signature of DG.DOTweenEditor.UI.DOTweenUtilityWindow:ConnectToSource due to: Could not load file or assembly 'DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type:<unknown type> member:(null) signature:<none>
Could not load signature of DG.DOTweenEditor.UI.DOTweenUtilityWindow:MoveSrc due to: Could not load file or assembly 'DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type:<unknown type> member:(null) signature:<none>
Could not load signature of DG.DOTweenEditor.UI.DOTweenComponentInspector:AppendTweenIdLabel due to: Could not load file or assembly 'DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type:<unknown type> member:(null) signature:<none>
Unloading broken assembly Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.dll, this assembly can cause crashes in the runtime
(Filename: C:\buildslave\unity\build\Runtime/Mono/MonoManager.cpp Line: 1233)
Unloading broken assembly Assets/Editor/UwaProjScan.dll, this assembly can cause crashes in the runtime
(Filename: C:\buildslave\unity\build\Runtime/Mono/MonoManager.cpp Line: 1233)
Unloading broken assembly Library/ScriptAssemblies/Demigiant.dll, this assembly can cause crashes in the runtime
(Filename: C:\buildslave\unity\build\Runtime/Mono/MonoManager.cpp Line: 1233)
|
分析
查看 Editor.log,可以看到问题发生在 Reloading assemblies for play mode.
,即第二次点击 Play 按钮时。
最诡异的就是这里,首次打开项目没问题,只有在某些情况下才会出现这个问题。首先是要确定如何稳定复现,经过不断尝试,找到一条稳定复现的路径:打开游戏,进入到特定场景触发动画后。
然后确定如何恢复,发现出现问题后无法恢复,只能重启 Unity 编辑器。接下来就是各种尝试,发现删除游戏逻辑 DLL A 后 B 中出现编译错误。
Unity 会将所有脚本编译成 DLL 再进行使用,支持 Assembly Definition
或者编译好的 DLL。游戏内 DLL 依赖关系是 A -> B -> Others,因此 B 中不可能存在依赖 A 的情况,否则形成循环引用,Unity 会无法成功编译所有脚本。
正常形况下不会有循环依赖问题,因为在 B 中使用 A 的 API,Rider 会自动在 B 的 Assembly Definition
中添加对 A 的引用,并且代码中会增加对 A 的命名空间的 using 指令。
出问题的地方是 A 中实现了一个 GameObject
的扩展方法,这种使用 Rider 并不会添加 using 指令,并且 Rider 也不会增加 Assembly Definition
的依赖引用。
复现
直接在启动时调用扩展方法,然后第二次运行就会报错了。
检查
在 Rider 中的 Project 视图可以看到 B.csproj 的 References
中有 A,但是 Unity 的 B.asmdef 的 Assembly Definition References
就没有 A。
因此如果想要自动检查是否有问题,可以通过重载脚本事件来检查 csproj 里是否存在不该有的 DLL 引用。
复盘
这个问题最诡异的是只在运行到某些时候发生,其实是在运行到不该引用的 DLL 内的方法时,DLL 出现了循环依赖而导致 Unity 后续编译失败。
建议只在共同依赖中添加扩展方法,以防止 Rider 在编写代码时偷偷自动地提示扩展方法。
此问题同时出现在了 Unity 2019.4.32f1 与 Unity 2022.3.46f1 中,基本可以确定这是一个跨多个版本的问题,只能想办法尽可能规避。