# UnityFPSUnlocker is a root module that raises the frame cap in IL2CPP Unity games

> UnityFPSUnlocker is a Magisk, KernelSU or APatch module, with an optional LSPosed variant, that changes the frame rate limit inside IL2CPP Unity games on Android by rewriting game memory at load time, and it ships a per package configuration file for FPS, delay, opcode patching and resolution scaling. It suits a player on a high refresh screen, and it modifies another application's memory, which some anti cheat systems detect.

**hexstr/UnityFPSUnlocker** — 为unity-il2cpp提供在手机上设置FPS的模块

- Repository: https://github.com/hexstr/UnityFPSUnlocker
- Stars: 537 · Forks: 54
- Language: C++
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/hexstr-unityfpsunlocker

## What the module actually changes

The repository description is narrow: it provides a module for setting FPS on a phone for unity-il2cpp games. The mechanism is memory patching inside the running game rather than a graphics setting. The module loads into the target process and alters the value that the Unity engine reads as its frame rate limit, so the game renders at the rate you ask for rather than the rate the developer shipped. The README is explicit about the detection risk in one of its configuration options: mod_opcode asks whether to modify the opcode, and the advice is that if you find the game relocks the FPS you can set this to true, but because it modifies memory it may be detected by anti cheat software. That sentence is the honest summary of the whole project. The module is MIT licensed, the default branch is zygisk_module, and the last push to the repository was on 2026-06-20, with releases 5.0.3 on 2026-06-20, 5.0.2 on 2026-06-09 and 5.0.1 on 2026-01-26. The tree carries a CMakeLists.txt, a UnityFPSUnlocker/ source directory and the two configuration files, TargetList.json and TargetList_jp.json.

## The root requirements and the two install variants

The installation prerequisites are specific and the module does not work around them. Your device needs Magisk, KernelSU or APatch installed. You need Zygisk enabled, and for KernelSU or APatch users that means installing Zygisk Next. If you take the Xposed route, the Xposed implementation needs to be LSPosed. And the two routes are mutually exclusive: the Xposed module and the Zygisk module are a choice of one. There is a practical wrinkle with the Xposed variant. An Xposed module generally does not update together with the Magisk module, so the README tells you to scroll back through the releases to find the app-debug.apk. You can extract the newest zygisk_module.zip and its zygisk/{architecture}.so, replace the matching libUnityFPSUnlocker.so inside app-debug.apk's lib/{architecture} directory, and then re-sign the APK with an APK editor such as MT Manager. In other words, the Xposed path expects you to assemble the artifact yourself.

## TargetList.json and the global versus per package configuration

The configuration file is the part of the project you will actually spend time with. Before rebooting into the module you download TargetList.json, put it at /data/local/tmp/TargetList.json and edit it. The module decides whether to load into a game by checking whether the game's data directory contains /sdcard/Android/data/{package name}/files/il2cpp, so the file lists the packages you want affected and the settings for each.

```json
{
  "global": {
    "delay": 10,
    "mod_opcode": true,
    "fps": 90,
    "scale": 1.0
  },
  "custom": {
    "com.random.package.name.a": {
      "fps": 60
    },
    "com.random.package.name.b": {
      "mod_opcode": false
    },
    "com.random.package.name.c": {
      "delay": 5
    }
  }
}
```

The global block sets the defaults. The fps value is the frame rate to set, and setting it to 0 disables the module. The delay value is how many seconds to wait after the game loads before acting, which exists because patching too early can hit a game that has not finished initialising. The mod_opcode flag is the opcode modification described above. The scale value is a resolution multiplier that is generally left at 1.0 and must be a decimal, computed as the current screen width times scale by the current screen height times scale. The custom block overrides the global settings per package, keyed by the package name.

## Checking that it loaded and turning it off per game

The README gives two operational tools for verification and control. Edits to TargetList.json take effect immediately for module versions 1.8 and later, so there is no need to reboot for every change, and the README suggests searching for a JSON format validator to check that your edit is complete. To see what the module is doing, you run logcat -s UnityFPSUnlocker in a terminal emulator and read the tagged log output. The blacklist mechanism is how you exclude a game. For the Magisk module, you set the fps value for that package to 0 and the plugin does not take effect. For the Xposed module, you untick the application in LSPosed, and if the game does not appear in the list you select Hide, then Games, from the top right corner. Two further notes belong here as well. Some games detect this kind of module, and for those the README suggests keeping SELinux in strict mode with setenforce 1. And for games with detection that crash as a result, the README asks you not to file an issue.

## The resolution scaling feature and the Blue Archive example

Beyond the frame rate, the module can change the resolution the game renders at, and the README explains why it was added with a specific example. The note is about Blue Archive, whose maximum resolution turns out to be 1080P, which shows visible aliasing in an emulator and, in a 16:10 aspect ratio, produces fewer pixels than 16:9. The two cases are given as 2560x1600 becoming 1822x1138 against 2560x1440 becoming 1920x1080, and comparison images are linked. The scale option is how you ask for that. The README also documents a way to avoid the upscaling entirely if you do not want it, by editing /sdcard/Android/data/com.nexon.bluearchive/files/DeviceOption and changing the Resolution value to something greater than 3, which routes through the default branch in the function GraphicsManager.CoSetScreenResolution(). The documented values are 0 for 1080P, 1 for 720P, 2 for 540P, 3 for 480P, and default for the default behaviour. This is a fairly deep modification of the game's own configuration file, so it is worth knowing that the mapping exists before you go looking for it.

## Where this module is the wrong tool

Four limits are worth stating plainly. The first is that it only applies to IL2CPP Unity games. A Mono build, a native Android game or a game built with another engine is untouched, and the module's own detection heuristic looks for the il2cpp directory, so a game that packages its data differently will simply never load the module. The second is the anti cheat problem, which the README raises twice. The module works by writing to another application's memory, and it says plainly that the opcode modification may be detected by anti cheat software and that crashing games with detection should not be reported as issues. A player whose account is at stake should read that as a risk statement rather than a caveat. The third is the blast radius of the installation itself. Zygisk, and Zygisk Next on top of KernelSU or APatch, changes how processes start on your phone, and the module then injects into your games, so the trust footprint is the root solution plus the injection framework plus the patch, and a rooted daily driver with banking apps is a different risk profile from a test device. The fourth is the maintenance reality of an out of tree patch. The module hooks engine internals, and when a game updates its Unity version or its own anti cheat the patch may stop applying, and the workaround the project itself suggests, relocking FPS, is a symptom of exactly that. The reasonable alternative for someone who wants a higher frame rate is to check whether the game exposes a frame rate setting of its own, because many Unity games do, and the alternative for someone who wants to mod a game is a general purpose game modding framework that works inside the game's own scripting layer rather than patching its compiled memory.

## Conclusion

Adopt this module if you play an IL2CPP based Unity game on a high refresh rate display and the game caps itself below your screen's refresh rate, because it rewrites the cap in the game's own memory and lets you set a different FPS per package through a JSON file you can edit without reflashing. Do not adopt it if the game has anti cheat that inspects its own memory, since the README states the opcode patching may be detected, and do not adopt it if you are unwilling to run a Zygisk module on your daily driver phone. Verify two things before you flash it: that your game is built with IL2CPP rather than Mono, since the module decides whether to load by checking for the il2cpp directory in the game's data folder, and that your root solution exposes Zygisk, since the module will not work without it and KernelSU or APatch users need Zygisk Next installed. The practical first step is to put a TargetList.json in /data/local/tmp with the global block filled in for your package, then flash the module and watch logcat -s UnityFPSUnlocker to confirm it loaded.

## FAQ

### What is UnityFPSUnlocker?

It is a C++ module for Android that raises the frame rate limit in IL2CPP based Unity games by patching game memory, delivered as a Zygisk module for Magisk, KernelSU or APatch with an optional LSPosed variant. It is MIT licensed and the last push to the repository was on 2026-06-20.

### What does UnityFPSUnlocker require before it will work?

Your device needs Magisk, KernelSU or APatch, with Zygisk enabled, and KernelSU or APatch users need Zygisk Next installed. The Xposed route requires LSPosed, and the Xposed module and the Zygisk module are a choice of one rather than both.

### How do I configure UnityFPSUnlocker?

Download TargetList.json, put it at /data/local/tmp/TargetList.json and edit it before rebooting. The global block sets the defaults for fps, delay, mod_opcode and scale, and the custom block overrides them per package name. Changes take effect immediately for module versions 1.8 and later, and the README suggests validating the JSON before saving.

### How do I disable the module for a single game?

For the Magisk module, set the fps value for that package to 0 in TargetList.json and the plugin will not take effect. For the Xposed module, untick the application in LSPosed, and if the game is not listed use the Hide, then Games, option in the top right corner.

### Can UnityFPSUnlocker cause a game to crash?

The README says that for games with detection, if a crash occurs you should not submit an issue. It also suggests keeping SELinux in strict mode with setenforce 1 for games that detect this kind of module, and notes that changing the mod_opcode option to true modifies memory in a way anti cheat software may detect.

## Sources

- [hexstr/UnityFPSUnlocker on GitHub](https://github.com/hexstr/UnityFPSUnlocker)
- [Issues](https://github.com/hexstr/UnityFPSUnlocker/issues)
- [License: MIT](https://github.com/hexstr/UnityFPSUnlocker/blob/zygisk_module/LICENSE)
- [README](https://github.com/hexstr/UnityFPSUnlocker/blob/zygisk_module/README.md)
- [Releases](https://github.com/hexstr/UnityFPSUnlocker/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hexstr-unityfpsunlocker
