{
  "id": 19450190,
  "title": "Obfuscating Unity Game Assemblies: Mono, IL2CPP, and the Keep-Rules Serialization Demands",
  "url": "https://urgent.news/2026/11/11/obfuscating-unity-game-assemblies-mono-il2cpp-and-the-keep-rules",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-11-11T05:23:11.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/zero_heartbeat_06a3625d7a/obfuscating-unity-game-assemblies-mono-il2cpp-and-the-keep-rules-serialization-demands-3i3j"
  },
  "original_language": "en",
  "account": "When you create a Unity game using the Mono scripting backend, you are essentially revealing your source code. The Assembly-CSharp.dll file in the player's Managed folder is ordinary .NET IL, which can be easily decompiled into readable C#. To hide your game's secrets, obfuscation is the go-to solution. However, Unity is the only .NET environment where naive renaming can break your game due to its heavy reliance on name-based serialization and reflection. The obfuscator must be instructed to leave certain elements untouched. This article explores the differences between Unity's Mono and IL2CPP backends, what Unity resolves by name, and the keep-rules for aggressive obfuscation without breaking your game. Unity offers two scripting backends: Mono and IL2CPP, each impacting how obfuscation is implemented. Mono compiles scripts into managed assemblies (.dll files) that can be decompiled and fully obfuscated. In contrast, IL2CPP transpiles managed IL to C++ and compiles it into native libraries for specific platforms. While IL2CPP does not expose a managed assembly to rename at runtime, it generates a global-metadata.dat file that contains type, method, and field names, as well as string literals in clear text. To protect your game, you must transform the managed assemblies before IL2CPP runs to encrypt or rename the names and strings that get baked into global-metadata.dat. Unity's serialization heavily relies on name-based binding across various aspects like serialized fields, script type references, UnityEvent listeners, string-dispatched calls, and lifecycle hooks. Blind renaming could corrupt your game by breaking the links between these elements. To avoid this, the goal is to keep only the names Unity binds to and obfuscate everything else. Unity provides a keep-list/rename-exclusion mechanism through its keep-rules, which allows you to specify the names of UnityEngine.MonoBehaviour and UnityEngine.ScriptableObject subclasses, all serialized members on those types, and any methods targeted by UnityEvent or called via SendMessage, Invoke, or AnimationEvent. By applying these rules, you can obfuscate your code aggressively without breaking the game.",
  "summary": "Ship a Unity game built on the Mono scripting backend and you have, in effect, published your source code. The Assembly-CSharp.dll sitting in your player's Managed folder is ordinary .NET IL, and a decompiler turns it back into readable C# in seconds — your combat formulas, your anti-cheat, your in-app-purchase validation, your secret URLs, all right there. Obfuscation is the standard answer, but…",
  "key_points": [
    "Unity's Mono backend reveals source code in Assembly-CSharp.dll",
    "IL2CPP backend transpiles to C++ without exposing managed assembly",
    "Keep-rules specify names to preserve during aggressive obfuscation"
  ],
  "editors_take": "Protecting Unity code requires a surgical approach to obfuscation because the engine's reliance on name-based serialization means that indiscriminate renaming will inevitably corrupt vital links between scripts and game assets.",
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}