IL2CPP Compatibility
Some protections can’t survive a Unity IL2CPP build. Mark those with [IL2CPPIncompatible] and
BitMono skips them automatically whenever it runs in IL2CPP mode, while still running them normally on
Mono and standalone .NET.
[IL2CPPIncompatible("Emits calli, which IL2CPP's AOT compiler does not support")]
public class CallToCalli : Protection
The reason you pass is shown to the user, so they understand why it was skipped:
[IL2CPP] CallToCalli - Emits calli, which IL2CPP's AOT compiler does not support
Like the runtime moniker, the attribute is read by reflection, you
don’t register anything. Add it on top of the protection (built-in or a plugin) and
you’re done. IL2CPP mode is set automatically by the Unity integration when the scripting backend is
IL2CPP, or by hand with the CLI --il2cpp flag / "IL2CPP": true in obfuscation.json.
Should I mark my protection?
On an IL2CPP build the managed Assembly-CSharp.dll isn’t shipped, il2cpp.exe consumes it and
converts it to C++ (GameAssembly.dll). BitMono obfuscates before that conversion, so where your
protection’s output ends up decides this:
Don’t mark it if it only does managed metadata/IL edits
il2cpp.execan parse, renaming, clearing namespaces, swappingldstrfor a managed decryptor call. That effect carries through intoglobal-metadata.dat, which is exactly what you want.Mark it if it emits native code,
calli, packs the PE, or otherwise produces outputil2cpp.execan’t handle. It would either break the conversion or only touch the managed PE that IL2CPP throws away.
Note
Protections marked with Native Code ([ConfigureForNativeCode]) are treated as
IL2CPP-incompatible automatically, native method bodies can never become C++, so you don’t need to add
[IL2CPPIncompatible] on top of them as well.
See Unity Protections for which built-in protections run on IL2CPP and which are skipped.