Релевантные ссылки:
- [Оф. документация](https://harmony.pardeike.net/articles/intro.html)
- [Github](https://github.com/pardeike/Harmony)
> Не поддерживает IL2CPP, только .Net и Mono
HarmonyLib — это библиотека для .NET и Mono, которая позволяет модифицировать, заменять и декорировать методы во время выполнения приложения. Она широко используется для создания модификаций в играх, написанных на C#, таких как RimWorld, Subnautica и другие. HarmonyLib предоставляет разработчикам элегантный и высокоуровневый способ изменять функциональность приложений без необходимости изменять исходный код или перекомпилировать сборки.
### Установка
Я так и не смог установить библиотеку в Unity. Пока пытался это сделать, уже отпала нужда в нем.
Сначала я пытался установить либу через `NuGetForUnity`, но в подтянутых пакетах не оказалось dll.
Далее, Я скачал вручную из Nuget пакет, но и в нем для `.NET Standard` не было dll.
Далее, я скачал пакет из github-репозитория пакет. и в этом пакете уже был dll. Однако либа в Unity у меня так и не заработала. Выдавала ошибку:
```
PlatformNotSupportedException: System.Reflection.Emit.ILGeneration is not supported on this platform.
```
Переключение в настройках Unity с IL2CPP на Mono не помогло (этого не нужно было по идее делать, но решил перестраховаться)
Библиотека создана для того, чтобы делать инъекции в чужие игры на Unity (я думаю, цель всё-таки именно Unity, хотя либа подходит для .net в целом.). Ты создаешь чистый c#-проект и через него закидываешь свой dll с инъекцией в чужую игру, а там чужая игра запускает этот dll. По логике, значит можно и просто в своём проекте использовать данную либу для инъекции.
В документации не говорится, как на unity установить либу, но есть такая пометка (привёл ниже). Я так понимаю, что, что unity поддерживается, но не через "интерфейс" `.NET standard`
> Harmony works with all languages that compile to [CIL](https://wikipedia.org/wiki/Common_Intermediate_Language), Microsofts intermediate byte code language. This is foremost the [.NET Framework](https://wikipedia.org/wiki/Portal:.NET_Framework) and of course [Mono](https://wikipedia.org/wiki/Mono_(software)) - used by the game engine Unity.
>
>The exception is probably [Unity .NET Standard profile](https://docs.unity3d.com/2019.1/Documentation/Manual/dotnetProfileSupport.html), which does not provide the functionality to fully create methods on the fly at runtime.
Гитхабе есть разные Issue, по которым можно сделать выводы:
- Harmony НЕ поддерживает .NET Standard, потому что использует API, отсутствующие в нём.
- Unity поддерживает Harmony, но нельзя просто установить через NuGetForUnity (потому что NuGetForUnity подтягивает всегда пакеты с версией .NET Standard) . Нужно установить net472 вручную (не пробовал)
- При установке либы версии net472, скорее всего нужно изменить настройки Unity (Измените .NET Standard 2.1 на .NET Framework (обычно .NET Framework 4.x).)
[Compatibility with NugetForUnity #623](https://github.com/login?return_to=https://github.com/pardeike/Harmony/issues/623)
[Invalid metadata in the "Fat" build of v2.3.3.0 (leads to errors in Unity). #649](https://github.com/login?return_to=https://github.com/pardeike/Harmony/issues/649)
- По данному issue можно понять, что люди используют данную либу в своём проекте на Unity.
### Зачем мне нужна была данная библиотека
Я пытался понять, какой алгоритм в моем коде изменяет transform.rotation, а так как это класс от Unity, то я не мог посмотреть юсинги у rotation, поэтому пришла идея сделать инъекцию для settera у rotation (это свойство) и внедрить туда вывод stacktrace в лог.
```csharp
using System;
using System.Diagnostics;
using HarmonyLib;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace Modules.BaseGame.Unity.Monobehaviours
{
[HarmonyPatch(typeof(Transform))]
[HarmonyPatch("set_rotation")]
public class TransformRotationPatch
{
static void Prefix(Transform __instance, ref Quaternion value)
{
// Получаем текущий StackTrace
StackTrace stackTrace = new StackTrace(true);
string traceInfo = stackTrace.ToString();
Debug.Log(
quot;[Harmony] Rotation changed for {__instance.gameObject.name} to {value}");
Debug.Log(quot;[StackTrace]:\n{traceInfo}");
}
}
public class HarmonyPatcher : MonoBehaviour
{
void Start()
{
var harmony = new Harmony("com.example.rotationtracker");
harmony.PatchAll();
Debug.Log("Harmony patch applied to Transform.set_rotation");
}
}
}
```