SkillAgentSearch skills...

Unify

Automatically port Unity games for macOS or Windows to Linux

Install / Use

/learn @0xf4b1/Unify
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

unify

Automatically port Unity games for macOS or Windows to Linux

Games based on the Unity engine can be deployed and run on multiple platforms, including Linux. The platform-specific engine files are mostly generic, so we take the official game files and run them with Unity's Linux binaries. This way we get a native Linux version of the game without the need of compatibility layers, such as Wine.

This method can work as long as the game was exported with OpenGL or Vulkan renderer enabled. Windows versions usually default to DirectX and only rarely have OpenGL enabled, but macOS versions often have OpenGL enabled and chances are high to get them to run.

Many Unity titles are officially available for Linux, but there are also some cases where this method can create a missing Linux port. Lots of Unity Games that were availbale for free on Epic Games have been tested. Since Epic Games does not support Linux game versions, you can also benefit from this method to play your Unity games that you may have collected on that platform.

Take the Compatibility Status list as reference if you are only interested in games that are known to be playable.

Install Unity Games

To determine which games are based on Unity, you can check out steamdb.

Epic Games

You can download games with Legendary, the free and open-source Epic Games Launcher alternative.

List all your titles for macOS or Windows

legendary list --platform <Mac|Windows>

Install the macOS or Windows version of game with

legendary install --platform <Mac|Windows> <App name>

Steam

You can download Steam games for a specific platform with steamcmd. To download macOS versions, use the following command:

steamcmd +@sSteamCmdForcePlatformType macos

Inside steamcmd run the following:

login <account_name>
app_update <app_id>

Porting

Install requirements via pip:

pip install -r requirements.txt

Check available renderers of the game by using the script:

./renderers.py <game dir>

If the script outputs OpenGL Core or Vulkan as detected Graphics Apis, you are lucky and can continue! Otherwise you should stop here because the game does not contain shaders that work with Unity on Linux. If you still want to proceed, read through the Research section to see possible experimental ways to get the needed shaders or let me know if you have an idea!

If the game has a _Data directory prefixed with the game title (e.g. The Last Campfire_Data), you should rename it to just Data. Then run the script with the path of the Unity game as argument

./unify.sh <game dir>

The script probes the game for the Unity version, then downloads the relevant engine files and copies them into the game directory. If it succeeded, try to start the game via the LinuxPlayer binary. If it does not run, make sure to check the logs usually in ~/.config/unity3d/<vendor>/<title>. In most cases, the game misses some native libraries that need to be replaced. For Steam games it might work to just copy an arbitrary .so file to the place of the expected libsteam_api64.so.

The script will cache the downloaded and extracted unity files by default in the folder ~/Unity/Hub/Editor, but you can override this location using the UNITY_REPO environment variable.

If the script is not successful, the game may not be a Unity game or it may have a different structure. The script in its current state is very basic and does not cover all cases.

Research

Shader object extraction

Dump shader objects from games and use them in other games.

If a game needs the exact same shaders that are present in another game with the desired graphics api and same unity version, there is a chance that you can reuse the whole shader objects.

Shader object dumping

Dump shader objects from a game that supports the desired graphics api:

./shaders.py <game dir> --dump --shader_dir <shader_dump_dir>

Shader object replacing

Replace the shader objects in a game with previously dumped ones:

./shaders.py <game dir> --replace --shader_dir <shader_dump_dir>

Force the game to use a different graphics api by patching file globalgamemanagers, e.g. 17 for OpenGL Core:

./renderers.py <game dir> --force 17

Shader compilation

Compile missing shader objects with Unity directly

Buildin-shader source code can be downloaded from the unity archive per unity release, for example builtin_shaders-6000.2.1f1.zip. Other shader source code provided via packages should possibly be located on the filesystem after installing. By creating and exporting a Unity project that contains the shader objects with the desired graphics api, they can be extracted as described above.

Compile shader code by using UnityShaderCompiler directly

The Unity Editor comes with a dedicated UnityShaderCompiler executable. The Unity Editor opens a port and starts instances of the UnityShaderCompiler with parameters to connect to Unity's open port. The communication can be intercepted by setting up a proxy, like described here. As proxy tool, tcpprox can be used for example. The communication is a proprietary protocol that needs to be analyzed. One of the supported commands is c:compileSnippet that Unity sends followed by plain shader source code to receive compiled shaders and other information back.

Shader translation via cross-compiling

For games that come only with DirectX and no way to get the shader sources, try to translate DXBC to OpenGL or Vulkan shaders.

Translate DirectX byte-code (DXBC) to OpenGL

HLSLcc: https://github.com/0xf4b1/unify/issues/11 HLSLcc is part of Unity's shader compiler, see docs.

In the hlslcc branch is an attempt to use the library to translate DXBC to OpenGL. The translation works for the test DXBC object, however it crashes on dumped DXBC objects from unity for yet unknown reasons.

Translate DirectX byte-code (DXBC) to SPIR-V (Vulkan)

  • DXVK: DXVK reimplements the DirectX api calls to target Vulkan. This means it must also handle shader translation from DirectX (DXBC) -> Vulkan (SPIR-V). The needed functionality for the translation should start here.

  • DirectXShaderCompiler: For compiling shader source code and possibly DXBC to SPIR-V using the SPIR-V CodeGen.

Unity shader object rewriting

Rewrite Unity shader objects with new shader code.

Even if there is a way to directly translate shader byte-code to another graphics api, only replacing the shader code does not work as Unity's shader object contains much for information which means all this required information that Unity writes into the object need to be determined to be able to rewrite the whole unity shader object so that the shader can run.

More compatibility

  • Support for macOS (OpenGL is supported on macOS): https://github.com/0xf4b1/unify/issues/4
  • Research if Android is possible (OpenGLES is supported on Windows): https://github.com/0xf4b1/unify/issues/7

Useful tools

Compatibility Status

macOS

| App title | App name | Unity version | Linux available | OpenGL enabled | Playable | Notes | |-----------------------------------|----------------------------------|---------------|-----------------|----------------|----------|-----------------------------------------------| | Duskers | 1e9c3a9a10c6463e9c065f371b8b42bf | 5.3.4f1 | yes | yes | yes | | | Sunless Sea | 2420b50453144c07b3b847fff941275d | 5.5.1f1 | yes | yes | no | can not find matching unity engine | | Darkwood | 923130ebb546417b9d3115507f752d34 | 5.5.3f1 | yes | yes | no | can not find matching unity engine | | Night In The Woods | cd1b8a6e5b6c47369e2a1e2cf7b7f536 | 5.6.2p4 | yes | yes | no | can not find matching unity engine; 5.6.2xf1Linux can be used instead[^4]; needs fmod 1.7.8[^3] | | Stories Untold | Parsley | 5.6.3p2 | no | yes | no | can not find matching unity engine; 5.6.3xf1Linux can be used instead[^4]; needs fmod 1.8.0[^3]; needs AVProVideo and more | | Inside | Marigold | 5.6.6f2 | no | yes | no | can not find matching unity engine | | The First Tree | cd98b47155654e1f9a9e84e60d0b49e4 | 2017.4.11f1 | yes | yes | yes | rewired: Rewired_OSX_Lib.dll must be removed | | Absolute Drift | 19927295d6e3467887d4e830d8c85963 | 2017.4.16f1 | yes | yes | no | needs EOSSDK-Mac-Shipping[^1]; rewired: Assembly-CSharp.dll needs to be patched[^2]; starting but unplayable due to white screen | | Enter the Gungeon | Garlic

View on GitHub
GitHub Stars68
CategoryDevelopment
Updated3d ago
Forks3

Languages

Python

Security Score

100/100

Audited on Mar 31, 2026

No findings