Desktop - Mod Loader - Detector (Pro)
Mod loaders such as 'BepInEx', 'MelonLoader', 'UnityDoorstop', 'HarmonyLib', or 'MonoMod' attach themselves to your game on desktop platforms (Windows, macOS, Linux) and load arbitrary code into your process. Because these loaders typically hook in before your C# runtime starts, blocking them from inside Unity is not feasible. Use the 'ModLoaderDetector' to reliably detect their presence and react accordingly.
Detector
The 'ModLoaderDetector' does not require any monitor. On demand, it performs three independent scans to spot a mod loader:
Loaded managed assemblies: Iterates 'AppDomain.CurrentDomain.GetAssemblies()' and matches each assembly's name against the configured assembly-name prefixes (e.g. 'BepInEx', 'MelonLoader', 'HarmonyLib', 'Mono.Cecil', 'MonoMod', '0Harmony').
Loaded native modules: Asks the platform-specific 'IPlatformProbe' for suspicious native modules. On Windows this includes 'UnityDoorstop' signatures - a 'winhttp.dll' or 'version.dll' loaded from the game directory instead of 'System32' - and well-known injector DLLs. On macOS and Linux, native module scanning is currently a no-op and reserved for a future native plugin probe.
Game folder layout: Scans the directory next to the game executable for known mod-loader files and folders (e.g. 'BepInEx/', 'MelonLoader/', 'doorstop_config.ini', 'Mods/').
Observed Subject
The detector does not observe any monitor. It runs an on-demand scan when 'ManualScan()' is invoked or, if enabled, automatically during 'Start' and on a configurable interval.
Status
When a mod loader is found, the detector notifies its observers with a DesktopCheatingDetectionStatus, which implements IDesktopCheatingDetectionStatus (and therefore IDetectorStatus):
public struct DesktopCheatingDetectionStatus : IDesktopCheatingDetectionStatus
{
// Probability that the detection is a false positive, in the range [0.0, 1.0].
public float PossibilityOfFalsePositive { get; }
// The threat rating reported with this detection.
public uint ThreatRating { get; }
// The type of cheating detected on the desktop platform.
public EDesktopCheatingType DesktopCheatingType { get; }
// A short, human-readable string describing what triggered the detection.
public string Evidence { get; }
}
- Evidence: For example the matching assembly name, file path, or native module name.
For this detector, DesktopCheatingType can be:
public enum EDesktopCheatingType : byte
{
MOD_LOADER_ASSEMBLY = 10, // A managed mod-loader assembly is loaded into the AppDomain.
MOD_LOADER_FILE = 11, // A mod-loader file/folder was found next to the executable.
MOD_LOADER_INJECTOR = 12 // A mod-loader injector native module is loaded (Windows only).
}
Threat rating and false positives
- PossibilityOfFalsePositive: default
0.02(range 0-1). Low, because the configured prefixes / file names are very specific. - ThreatRating: default
500(recommended 500). High, because mod loaders give the user complete access to the game.
Configuration
- Is Active (
isActive, bool, default true) - whether the detector is active and watching. - Possibility Of False Positive (
possibilityOfFalsePositive, float, default 0.02, range 0-1). - Threat Rating (
threatRating, uint, default 500). - On Cheating Detection Event (
OnCheatingDetectionEvent) - a UnityEvent raised on every detection. - Check Only On Game Start (
CheckOnlyOnGameStart, bool, default false) - run the scan only once on start; disable to also run a periodic recheck. Recommended false, because rechecks catch late-injected mod loaders. - Recheck Interval For Possible Cheating (
RecheckIntervalForPossibleCheating, float, default 30, range 1-600) - interval in seconds between scans.
The assembly prefixes and file names to scan for are configured in the global project settings (see 'Configure Desktop Settings' below).
Supported Platforms
The detector is available on Windows, macOS, and Linux Standalone players. Managed assembly and file-system scans run on all three platforms. Native module scanning is currently implemented for Windows; on macOS and Linux the native scan returns an empty result and is reserved for a future native plugin.
Requirements
There are no native requirements; the detector uses managed APIs and platform P/Invokes provided by the package. In the Unity Editor and in Development Builds, the detector only runs when 'Desktop_Enable_Development' is enabled in the global AntiCheat settings.
How To Use
The usage is straightforward: attach a 'ModLoaderDetector' to a child GameObject of the 'AntiCheat-Monitor', configure the global Desktop settings, and define a reaction to detected cheating.
Requirements
There are none. No additional monitor is required.
Add Detector Component
Manual
Add the 'ModLoaderDetector' MonoBehavior from the 'GUPS.AntiCheat.Detector.Desktop' namespace to your 'AntiCheat-Monitor' GameObject, or better, to a child GameObject.

Add the 'ModLoaderDetector' as a Component.
Settings
After attaching the 'ModLoaderDetector' MonoBehavior to a GameObject, you will see the following in the inspector:

The settings of the 'ModLoaderDetector' Component.
- General Settings: Define here whether the detector should be active.
- Threat Rating Settings: Define here the severity of the detected cheating.
- Observable Settings: Add here callbacks invoked when cheating is detected.
- Mod Loader Settings: Set whether the scan runs once on Start and/or repeats on a configurable interval.
Runtime
On Start (and on the configured interval), the detector calls its scans and notifies observers if a mod loader is found. You can also trigger 'ManualScan()' yourself, for example after loading a level or returning from a menu.
Configure Desktop Settings
Open 'Edit -> Project Settings -> GuardingPearSoftware -> AntiCheat' and switch to the 'Desktop' tab.

In the AntiCheat Project Settings, configure the Desktop mod loader detection.
Use the following entries to control this detector:
- Enable in Development: 'Desktop_Enable_Development'. Set to true to allow detection inside the Unity Editor and Development Builds. Off by default.
- Detect Mod Loader: 'Desktop_DetectModLoader'. Master switch for this detector. On by default.
- Mod Loader Assembly Prefixes: 'Desktop_ModLoader_AssemblyPrefixes'. List of case-insensitive assembly-name prefixes that should be considered a mod loader (e.g. 'BepInEx', 'MelonLoader', 'HarmonyLib', '0Harmony', 'MonoMod', 'Mono.Cecil').
- Mod Loader File Names: 'Desktop_ModLoader_FileNames'. List of file or folder names that should be considered a mod loader if they are present next to the game executable (e.g. 'BepInEx', 'MelonLoader', 'doorstop_config.ini', 'winhttp.dll', 'version.dll', 'Mods').
When any of these lists is empty, the detector falls back to a built-in default list of well-known mod loaders.
Consume the detection in code
Besides the inspector event, you can subscribe your own observer. Every detector derives from ADetector and exposes Subscribe(IObserver<IDetectorStatus>), which returns an IDisposable you can dispose to unsubscribe. Cast the status to DesktopCheatingDetectionStatus to read the desktop-specific fields:
using System;
using GUPS.AntiCheat;
using GUPS.AntiCheat.Core.Detector;
using GUPS.AntiCheat.Detector.Desktop;
using UnityEngine;
public class ModLoaderDetectionLogger : MonoBehaviour, IObserver<IDetectorStatus>
{
private void Start()
{
var detector = AntiCheatMonitor.Instance.GetDetector<ModLoaderDetector>();
detector.Subscribe(this);
}
public void OnNext(IDetectorStatus status)
{
if (status is DesktopCheatingDetectionStatus desktopStatus)
{
Debug.LogWarning($"Mod loader detected: {desktopStatus.DesktopCheatingType} " +
$"(threat={desktopStatus.ThreatRating}, evidence={desktopStatus.Evidence}).");
}
}
public void OnError(Exception error) { }
public void OnCompleted() { }
}
React On Cheating
When the detector is set up, you surely want to react to detected cheating.
Punisher
In general, any cheat detected is forwarded to the 'AntiCheat-Monitor', which calculates an overall threat level. Based on the threat level, you can apply punishments by using Punisher components added to a child GameObject of the 'AntiCheat-Monitor'. There are some built-in punishers that you can find here as prefabs:

The location of the built-in Punisher prefabs.
Inspector
You can set a callback in the Unity Inspector view of the detector. This callback is invoked as soon as the specific cheating is detected.
Code
If you would like to write a custom listener for the detector, you can attach an observer:
// Get the detector.
var detector = AntiCheatMonitor.Instance
.GetDetector<ModLoaderDetector>();
// Subscribe as observer and get notified on inconsistency.
detector.Subscribe(myObserver);
The detector also has an inherited property 'PossibleCheatingDetected' which is set to true once cheating has been detected.