On this page

Mod support: sources and measurements

The research behind the modding skill and the untrusted-load architecture rule, gathered on 2026-10-21. It draws on the Godot 4.7.2 class reference and source, Godot's export documentation, Steamworks and mod.io documentation. Tests ran on Linux with Godot 4.7.2 (mono and standard), .NET 8 (SDK 8.0.131) and Xvfb: a C# game exported for Linux loaded a GDScript mod exported as PCK and ZIP, and a C# mod built with Godot.NET.Sdk/4.7.2. Marks: tested means run here, source means read in the engine code, doc means stated by the vendor, and unconfirmed means not verified.

Sources

Source What it gave
Godot 4.7.2 ProjectSettings.xml load_resource_pack(pack, replace_files = true, offset = 0): files in the pack win "unless replace_files is set to false"
Exporting packs, patches and mods Load packs early ("in the autoload script's _init()"); sign official patches with Crypto; "no out-of-the-box way to prevent someone from copying the PCK file"; Assembly.LoadFile("mod.dll") for C#
Godot 4.7.2 SceneMultiplayer.xml "Deserialized objects can contain code which gets executed"
Godot 4.7.2 GodotPlugins/Main.cs The game assembly is loaded into its own non-collectible context in an export; only it is scanned for scripts
Steam Workshop implementation The upload and install calls
mod.io docs, console, moderation SDKs, console tiers, moderation layers
Godot Mod Loader Documents a "workaround to mod scripts using class_name"

Packs in an exported game (tested)

A mod exported with --export-pack from the standard editor needed no export templates. PCK and ZIP gave identical results. The pack held the imported textures (.ctex plus .import), scenes converted to binary behind a .remap, the mod's GDScript as .gdc tokens (still code), data files named by the include filter, and also the mod project's project.binary, .godot/global_script_class_cache.cfg and .godot/uid_cache.bin.

Check, after load_resource_pack(..., true) Result
FileAccess read of a replaced data/items.json The mod's version at once (not cached)
load() of a texture the game had already preloaded Still the game's texture, the same object
ResourceLoader.load(path, "", CACHE_MODE_REPLACE) The mod's texture, and the reference already held changed too (updated in place)
load() of a scene not loaded before The mod's scene
A new mod scene, and load("uid://...") of the mod's texture Both load
load("uid://...") of a game texture after the mount Works (the UID cache is merged) and returns the mod's copy
ProjectSettings.get_global_class_list() Before: the game's classes; after: only the mod's
The mod's GDScript Used the game's class_name, wrote to user://, ran OS.execute("uname"): no sandbox

With replace_files = false the game's files stay, new mod paths still mount, a mod scene loads by path with an "invalid UID" warning, load("uid://<mod texture>") fails with Unrecognized UID, and a script using the mod's class_name fails with "Identifier ... not declared". The mod's GDScript still runs with full rights.

What follows for a mod loader:

Resources are code (tested)

C# mods in a mono export (tested)

In the exported game the game assembly lives in an IsolatedComponentLoadContext, not the default context, together with GodotSharp.dll.

How the mod DLL is loaded Result
AssemblyLoadContext.Default.LoadFromAssemblyPath Segfault (exit 139) on the first Godot call: the mod binds to a second, uninitialised GodotSharp. Not catchable
Assembly.LoadFile(path) (the Godot docs' advice) Segfault, same cause
new AssemblyLoadContext("ModAlc", true) with no resolver Segfault, same cause
AssemblyLoadContext.GetLoadContext(typeof(Game).Assembly).LoadFromAssemblyPath Works: static calls, new ModNode() added to the tree (its _Ready runs), Call("Ping")
A collectible context whose Load() returns the game context's assemblies Works
The DLL read from a mod pack with FileAccess.GetFileAsBytes, then LoadFromStream in the game context Works

Distribution (doc)

Policy and support

A mod policy (ownership, sale, redistribution of game assets), your own terms and takedown process outside Workshop, a "mods run code" warning, a "disable all mods" mode, active mods recorded in saves and crash reports, and a mod-list hash on joining a multiplayer game. Godot's MIT licence does not restrict modding; third-party assets in the game may.

Not confirmed