Companion implementation to Unity Doorstop. This provides a Doorstop.dll that Doorstop loads first, enables the Unity/Mono debug server, and adds a small hot‑reload mechanism for methods/ctors marked [Reloadable] in your mod assemblies.
Tested with Unity Doorstop v4.4.0 (Windows, Linux, macOS). See the latest release notes: https://github.com/NeighTools/UnityDoorstop/releases Uses ILReloaderLib v1.0.5 (Windows, Linux, macOS). See the latest release notes: https://github.com/pardeike/ILReloader/releases
- Unity player builds do not expose the Mono debugger by default. Doorstop can enable it at launch so you can attach a C# debugger (dnSpyEx / Rider / Visual Studio) to the shipping player.
- This repo’s loader also supports method‑level hot reload: when a DLL under
Mods/changes, patched copies are swapped in only for members annotated[Reloadable].
Define the attribute once in your mod (include it in the built DLL):
using System;
[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method)]
public class ReloadableAttribute : Attribute { }- Unity Doorstop v4.4.0 (multi‑platform; includes Linux + macOS builds)
↳ https://github.com/NeighTools/UnityDoorstop/releases - Harmony 2.4.1 (optional but common; arm64‑ready for Apple Silicon)
↳ https://github.com/pardeike/Harmony/releases - Debugger (pick one):
- dnSpyEx (Windows): https://github.com/dnSpyEx/dnSpy
- JetBrains Rider (Win/macOS): https://www.jetbrains.com/help/rider/Debugging_Unity_Applications.html
- Visual Studio (Windows): https://learn.microsoft.com/visualstudio/gamedev/unity/get-started/using-visual-studio-tools-for-unity
Rimworld-Doorstop does no longer include Harmony and instead uses the version that Rimworld loads. You need to point to Harmony in the ini file, see below!
-
Locate the RimWorld folder (default):
C:\Program Files (x86)\Steam\steamapps\common\RimWorld -
Install Doorstop
Download the latest Unity Doorstop release and copywinhttp.dllanddoorstop_config.ininext toRimWorldWin64.exe. -
Add this repository’s loader
Build or download this repo’s release and placeDoorstop.dllinto the same folder. -
Configure Doorstop (
doorstop_config.ini):[General] enabled=true target_assembly=Doorstop.dll redirect_output_log=false # point to the Harmony library for active reloading, first existing location is loaded [Harmony] harmony_library=Mods\HarmonyMod\Current\Assemblies\0Harmony.dll harmony_library=..\..\workshop\content\294100\2009463077\Current\Assemblies\0Harmony.dll [UnityMono] # If you need to override Mono's search path, set this (see Doorstop v4.2+ notes) dll_search_path_override= # Enable the Mono debug server and choose an address/port (default is 127.0.0.1:10000) debug_enabled=true debug_address=127.0.0.1:56000 debug_suspend=false
-
Build your mod in
Debugso the.pdbsits next to yourModName.dllin your mod’sAssemblies/folder. -
Run the game (via Steam as usual).
Your RimWorld folder should now contain (abridged):
Data/
Mods/
MonoBleedingEdge/
RimWorldWin64_Data/
Doorstop.dll <-- added (this repo)
doorstop_config.ini <-- added (Unity Doorstop)
winhttp.dll <-- added (Unity Doorstop)
RimWorldWin64.exe
...
Harmony is arm64‑ready; no Rosetta needed.
You’ll launch RimWorld via a tiny script so Doorstop preloads first.
-
Place files (next to the app bundle):
libdoorstop.dylib(from Unity Doorstop release)Doorstop.dll(from this repo)run.sh(launcher script below)
-
Create
run.sh(works for bothRimWorldMac.appandRimWorld.app):#!/usr/bin/env bash set -euo pipefail DIR="$(cd "$(dirname "$0")" && pwd)" APP="$DIR/RimWorldMac.app" [[ -d "$APP" ]] || APP="$DIR/RimWorld.app" BIN="$APP/Contents/MacOS/$(basename "$APP" .app)" # Inject Doorstop export DYLD_INSERT_LIBRARIES="$DIR/libdoorstop.dylib" # Launch with Doorstop CLI options exec "$BIN" \ --doorstop-enabled true \ --doorstop-target-assembly "$DIR/Doorstop.dll" \ --doorstop-mono-debug-enabled true \ --doorstop-mono-debug-address 127.0.0.1:56000 \ --doorstop-mono-debug-suspend false
Make it executable:
chmod +x ./run.sh
-
(If macOS blocks files) remove quarantine:
xattr -dr com.apple.quarantine ./libdoorstop.dylib ./run.sh ./RimWorldMac.app || true xattr -dr com.apple.quarantine ./RimWorld.app || true
-
Run
./run.sh
Where to find game assemblies on macOS:
~/Library/Application Support/Steam/steamapps/common/RimWorld/RimWorldMac.app/Contents/Resources/Data/Managed/Assembly-CSharp.dll
These steps mirror the current Linux section in the upstream README, updated for Doorstop v4.4.0.
-
Download the Linux Doorstop build from the Unity Doorstop release. Use a numbered release, not a CI build. Extract
x64/libdoorstop.soandx64/run.shinto the RimWorld game root.Common Steam paths (pick what matches your install):
~/.local/share/Steam/steamapps/common/RimWorld/(typical default)~/.steam/debian-installation/steamapps/common/RimWorld/(Debian/Ubuntu installer path)
-
Add this repository’s loader
Build or download this repo’s release and copyDoorstop.dllinto the same game root. -
Edit
run.sh— set these lines to match (ports are your choice):executable_name="RimWorldLinux" debug_enable="1" debug_address="127.0.0.1:50000" debug_suspend="1"
debug_suspend="1"makes the game wait until your debugger attaches (so it’s normal if nothing appears yet).- If your
run.shdoesn’t have these variables, use the CLI style instead (see Alternativerun.shbelow).
-
Launch & attach in Rider
Run./run.sh, then use Rider’s “Attach to Unity Process” / Unity configuration with Host127.0.0.1and Port50000. -
Breakpoints
You can set source breakpoints in your mod (needs PDBs). Breakpoints in RimWorld code require IL‑level tools (e.g., dnSpyEx).
Alternative run.sh (works on any distro; uses CLI flags directly):
#!/usr/bin/env bash
set -euo pipefail
DIR="$(cd "$(dirname "$0")" && pwd)"
BIN="$DIR/RimWorldLinux" # adjust if necessary
export LD_PRELOAD="$DIR/libdoorstop.so"
exec "$BIN" \
--doorstop-enabled true \
--doorstop-target-assembly "$DIR/Doorstop.dll" \
--doorstop-mono-debug-enabled true \
--doorstop-mono-debug-address 127.0.0.1:50000 \
--doorstop-mono-debug-suspend true- dnSpyEx (Windows):
Debug → Start Debugging → Debug engine: Unity, target127.0.0.1:<port>(e.g.,56000on Windows example). - Rider (Win/macOS/Linux):
Run → Attach to Unity Processor create a Unity attach config and set the host/port you chose. - Visual Studio (Windows):
Debug → Attach to Process…and connect to the Mono port.
Doorstop’s default Mono debug server is
127.0.0.1:10000. Using50000/56000is fine—just be consistent between config and your IDE.
Build the mod in Debug so symbols (.pdb) are present next to your DLL.
Windows (Steam default library):
- Game root:
C:\Program Files (x86)\Steam\steamapps\common\RimWorld - Managed code:
RimWorldWin64_Data\Managed\Assembly-CSharp.dll
macOS (Steam):
- Game root:
~/Library/Application Support/Steam/steamapps/common/RimWorld/RimWorldMac.app - Managed code:
RimWorldMac.app/Contents/Resources/Data/Managed/Assembly-CSharp.dll
Linux (Steam):
- Game root (typical):
~/.local/share/Steam/steamapps/common/RimWorld/ - Game root (Debian installer):
~/.steam/debian-installation/steamapps/common/RimWorld/ - Managed code:
<GameRoot>/RimWorldLinux_Data/Managed/Assembly-CSharp.dll
On macOS, right‑click the app → Show Package Contents to browse
Contents/...
- When a DLL inside
Mods/changes, the loader copies and patches it only for members marked[Reloadable]. - Ensure the assembly that defines
[Reloadable]is deployed with your mod before starting the game (so the attribute type exists when the game boots).
-
Can’t attach the debugger
Check that debugging is enabled (Windows:debug_enabled=true; macOS/Linux:--doorstop-mono-debug-enabled true), verify the port, and allow local loopback in your firewall. -
macOS: “Permission denied” or app/dylib blocked
chmod +x run.shand clear quarantine withxattr -dr com.apple.quarantine …(see steps above). -
Doorstop not loading on Windows
winhttp.dllanddoorstop_config.inimust sit besideRimWorldWin64.exe. Launchers that spawn the game in a different working directory can bypasswinhttp.dll—start from Steam or the actual exe. -
Breakpoints never hit (your mod)
Ensure your mod build isDebugand the.pdbis next to the DLL. -
Mono search path (Doorstop v4.2+ change)
If a needed dependency isn’t found early, setdll_search_path_override=indoorstop_config.inito include the directory that holds it.
- CLI flags on all platforms: Doorstop v4 uses
--doorstop-*flags; see the upstream README for the full list. - Default debug port:
127.0.0.1:10000. Change viadebug_address(config) or--doorstop-mono-debug-address(CLI). - Entrypoint: v4 expects
static void Doorstop.Entrypoint.Start(); this repo already provides it.