Unity Protections
This section lists various protections compatible with the Unity Engine.
Unity Runtime is typically based on the .NET Framework 4.*, depending on the Unity version in use. However, it is primarily executed on Mono, with Unity using its own fork of Mono specifically for Unity Runtime.
You can also refer to this list for Mono runtime protections, but be aware that while Unity’s Mono fork is similar to the standard Mono runtime, there may be differences that could impact compatibility.
Protection List
StringsEncryption Can significantly slow down your application.
BitDotNet Do not use with Unity versions higher than 2020.*. and instead use BitDecompiler
BitMethodDotnet
DotNetHook
CallToCalli
ObjectReturnType Unstable.
NoNamespaces May cause issues if you rely heavily on Reflection.
FullRenamer May cause issues if you rely heavily on Reflection.
AntiDebugBreakpoints Unstable.
AntiDecompiler
BitDecompiler
BitTimeDateStamp
BitMono
BillionNops
AntiDe4dot
AntiILdasm
The list above targets the Mono scripting backend, where the protected Assembly-CSharp.dll ships
as-is.
IL2CPP builds
With the IL2CPP scripting backend the managed assembly is not shipped: il2cpp.exe consumes it and
converts it to C++ (GameAssembly.dll), keeping a copy of every class/method/field name in
global-metadata.dat. That metadata is what tools like Il2CppDumper
read to reconstruct your code, so the useful obfuscation is whatever survives into the metadata.
BitMono obfuscates the managed assembly before il2cpp.exe runs, so name and string obfuscation carry
through into global-metadata.dat. The Unity integration detects the IL2CPP backend automatically (or set
"IL2CPP": true in obfuscation.json / pass --il2cpp to the CLI) and runs only the
IL2CPP-compatible protections, skipping the rest with a clear log line for each.
IL2CPP-compatible (kept):
FullRenamer - renamed names are written cloaked into
global-metadata.dat.NoNamespaces - clears namespaces in the metadata.
StringsEncryption - removes plaintext strings from the metadata; the decryptor is AOT-compiled to C++.
AntiDebugBreakpoints - pure managed timing checks that AOT-compile and still run at runtime.
Skipped on IL2CPP (would break the il2cpp.exe build, or only affect the discarded managed PE):
UnmanagedString, CallToCalli, DotNetHook, BitMethodDotnet, ObjectReturnType,
AntiDe4dot, BillionNops, AntiILdasm, BitTimeDateStamp, AntiDecompiler, BitMono,
BitDotNet, BitDecompiler.
Inspecting the metadata
To see what actually ended up in a build’s global-metadata.dat (its il2cpp version, and how many
identifier names and string literals it carries), point the CLI at the file:
BitMono.CLI --inspect-metadata "path/to/global-metadata.dat"
It just reads and prints - it doesn’t change the file. It also splits the names into reserved ones that
must never be renamed (Awake, Start, constructors, anything the engine looks up by name) and
rename candidates. If the candidates still read like plain English, your renaming didn’t reach the
metadata. Handy for confirming your names came through obfuscated, or before reporting a metadata issue.
Note
The full job of protecting the IL2CPP output itself - encrypting global-metadata.dat and
injecting a native decryptor into GameAssembly.dll - is tracked in
#276. The --inspect-metadata reader above is
the first piece of it; the native decryptor half is still to come.
Additional Considerations
Some of these protections may not be suitable for all Unity versions or Mono runtimes.
When using optional protections like NoNamespaces or FullRenamer, ensure to test thoroughly if your application uses extensive Reflection, as they might break functionality.