Добрый день. Как вы наверно знаете, с ноября 2014 Unity начала выкладывать исходный код подсистемы UI, а с марта 2017 — исходный код движка и редактора. И хотя их коммиты не всегда успевают за релизами, по крайней мере можно покурить почитать код и понять логику работы движка, более того — если собрать проект и подменить dll в каталоге установки Unity — с большой вероятностью Unity будет корректно работать. Естественно возникает вопрос — можно ли отлаживаться с пересобранной dll, погружаясь в дебри движка? И как вы понимаете, ответ — да, хотя информацию об этом в интернете пришлось собирать по крупицам, комбинируя подходы и экспериментируя, что и послужило причиной данной статьи.
Сейчас будет краткое объяснение процесса, если вам нужны конкретные инструкции — можете скипнуть эту часть.
Итак, если мы просто подменим dll подсистемы Unity на свою, мы ничего не получим — Unity будет работать, но зайти в код движка будет нельзя. Это происходит потому, что Unity исполняется на Mono Runtime, а не на .NET Runtime. Версия Mono Runtime, поставляемая с Unity, может исполнять .NET dll, собранные для .NET Runtime 2.0 для фреймворка .NET Framework 3.5 (в последних Unity появилась экспериментальная поддержка .Net Framework 4.6). Во время отладки пользовательских скриптов Visual Studio пользуется не отладчиком .NET, а отладчиком, встроенным в Mono Runtime — Mono Soft Debugger. Visual Studio общается с ним по определенному протоколу через плагин Visual Studio 2015 Tools for Unity, который ставится
Если плагин установлен — то в солюшене, созданном с помощью Unity стандартный дебаггер подменяется на Mono и кнопка Debug заменяется на Attach to Unity.
Чтобы Visual Studio мог отлаживать .NET dll, нужно собрать ее в варианте Debug — тогда вместе с dll сгенерируется pdb файл отладки, в котором прописано соответствие инструкций в dll строчкам кода в исходниках и где их искать, а в dll помимо прочего встраивается информация где искать pdb. Отладчику Mono для отладки mono dll необходим файл отладки другого формата — mdb. По умолчанию Mono Debugger ищет mdb рядом с dll — если вы откроете каталог с компонентами Unity EditorData, то увидите что все dll там идут с mdb файлами, внутри которых прописаны пути к исходникам на машине разработчиков Unity, которых у нас естественно будут другие. Чтобы получить mdb файл, в составе Unity есть утилита pdb2mdb.exe, которая преобразует файл отладки из pdb формата в mdb формат, но она у меня не работает, выдавая ошибку
"c:Program FilesUnity2017.2.0f3EditorDataMonoBleedingEdgebincli.bat" "c:Program FilesUnity2017.2.0f3EditorDataMonoBleedingEdgelibmono4.5pdb2mdb.exe" UnityEngine.UI.pdb
Fatal error:
System.BadImageFormatException: Format of the executable (.exe) or library (.dll) is invalid.
at Mono.Cecil.PE.ImageReader.ReadImage () [0x00026] in <97446e53703944aa97ee13e7d5ff6b85>:0
at Mono.Cecil.PE.ImageReader.ReadImage (Mono.Disposable`1[T] stream, System.String file_name) [0x00007] in <97446e53703944aa97ee13e7d5ff6b85>:0
at Mono.Cecil.ModuleDefinition.ReadModule (Mono.Disposable`1[T] stream, System.String fileName, Mono.Cecil.ReaderParameters parameters) [0x00006] in <97446e53703944aa97ee13e7d5ff6b85>:0
at Mono.Cecil.ModuleDefinition.ReadModule (System.String fileName, Mono.Cecil.ReaderParameters parameters) [0x0006c] in <97446e53703944aa97ee13e7d5ff6b85>:0
at Mono.Cecil.ModuleDefinition.ReadModule (System.String fileName) [0x00007] in <97446e53703944aa97ee13e7d5ff6b85>:0
at Mono.Cecil.AssemblyDefinition.ReadAssembly (System.String fileName) [0x00000] in <97446e53703944aa97ee13e7d5ff6b85>:0
at Pdb2Mdb.Converter.Convert (System.String filename) [0x00000] in <1279233ce2304b44acb52c964b80239f>:0
at Pdb2Mdb.Driver.Main (System.String[] args) [0x0001d] in <1279233ce2304b44acb52c964b80239f>:0
По счастью, эту же работу выполняет и плагин Visual Studio 2015 Tools for Unity при работе с нативными плагинами — надо просто бросить dll вместе с pdb в чистый проект Unity — и pdb сконвертируется в mdb.
Итак, конкретные шаги на примере UnityEngine.UI.dll:
- берешь свежие исходники Unity.UI из источников, указанных выше
- пересобираешь солюшн
- кидаешь Unity-Technologies-uiuiUnityEngine.UI-EditorbinDebugUnityEngine.UI.dll, pdb в какой-нибудь новый проект -> создается UnityEngine.UI.mdb
- заменяешь UnityEngine.UI.pdb, mdb в EditorDataUnityExtensionsUnityGUISystem
- удаляешь в таргетном проекте Unity все, связанное с VS (.sln, .csproj)
- пересоздаешь в нем проект VS (просто кликнув на любой скрипт)
- добавляешь в него Unity-Technologies-uiuiUnityEngine.UI-EditorUnityEngine.UI-Editor.csproj
- ставишь брейкпоинт в потрохах UI — работает!
Автор: Наташа