A BepInEx plugin for FUMES that replaces vehicle meshes at runtime using Unity AssetBundles. Lets you drive a completely different body shape — the Caro pickup conversion is the reference implementation.
Game: FUMES (Unity 2021.1.29f1, IL2CPP)
BepInEx: 6.0.0-be.755 (IL2CPP build)
- Replace any mesh on a vehicle hierarchy by name
- Per-vehicle JSON config — drop multiple mods side-by-side
- Supports both the Cars list (ready-to-drive) and the Body list (garage assembly)
- Patches
VehicleBodyfields: lamp positions, grill/interior/engine pivots, cargo hooks, light shaft transforms - Patches hardpoint positions (weapon/cargo slots) before the game places weapons in
Vehicle.Awake - Patches antenna position
- Material-slot fixer: trims excess material slots every frame so the skin system stays stable
- F3 key cycles submesh→material mapping (diagnostic)
- Install BepInEx IL2CPP bleeding edge build (build 755 or compatible) into the FUMES directory.
- Copy
MeshReplacer.dlltoBepInEx/plugins/. - Create the mod data directory:
BepInEx/plugins/meshreplacer/. - For each custom vehicle, create a subdirectory and add a
vehicle.jsonplus AssetBundle files:
BepInEx/plugins/
MeshReplacer.dll
meshreplacer/
caro-pickup/
vehicle.json
carobody ← AssetBundle (no extension)
caroreardoor ← AssetBundle
...
All vehicle.json fields are optional except id and baseBodyId. Fields set to null or omitted are left unchanged.
- .NET 6 SDK
- FUMES installed via Steam (for the interop DLLs)
- BepInEx 6.0.0-be.755 unpacked in the game directory
- Clone the repository.
- Copy the required DLLs into the
libs/directory at the repo root (see Required DLLs). - Build:
dotnet build MeshReplacer/MeshReplacer.csproj --configuration Release
The output is MeshReplacer/bin/Release/net6.0/MeshReplacer.dll.
Copy these files into the libs/ folder before building. They are generated by BepInEx from the game's IL2CPP binary and are not included in the repository.
| File | Source |
|---|---|
BepInEx.Core.dll |
FUMES/BepInEx/core/ |
BepInEx.Unity.IL2CPP.dll |
FUMES/BepInEx/core/ |
Il2CppInterop.Runtime.dll |
FUMES/BepInEx/core/ |
0Harmony.dll |
FUMES/BepInEx/core/ |
Assembly-CSharp.dll |
FUMES/BepInEx/interop/ |
Il2Cppmscorlib.dll |
FUMES/BepInEx/interop/ |
UnityEngine.dll |
FUMES/BepInEx/interop/ |
UnityEngine.AssetBundleModule.dll |
FUMES/BepInEx/interop/ |
UnityEngine.CoreModule.dll |
FUMES/BepInEx/interop/ |
UnityEngine.InputLegacyModule.dll |
FUMES/BepInEx/interop/ |
UnityEngine.PhysicsModule.dll |
FUMES/BepInEx/interop/ |
FUMES/ is the Steam game directory, typically C:\Program Files (x86)\Steam\steamapps\common\FUMES\.
Pre-built DLLs are published on the Releases page. Each release is built automatically from the tagged commit via GitHub Actions.
{ "id": "body-caro-pickup", // unique ID, used as license plate marker "baseBodyId": "body-caro", // existing BodyType to clone from "displayName": "Caro Pickup", "vehicleMarker": "CaroModel", // root GameObject name on the vehicle "meshReplacements": [ { "bundle": "carobody", // AssetBundle filename (relative to this folder) "candidates": ["Caro_Pickup(6)"], // asset names to try in order "target": "CaroModel", // GameObject to replace mesh on "isBody": true, // mark as the primary body mesh "fixMaterialSlots": false }, { "bundle": "caroreardoor", "candidates": ["Caro_Pickup-reardoor"], "target": "CaroDoorRear", "isBody": false, "fixMaterialSlots": true // trim excess material slots each frame } ], "vehicleBody": { "grillPosition": [0, 0.72, 1.72], "interiorCameraPosition": [0, 1.3, 0.2], "enginePosition": [0, 0.65, 0.9], "frontLampsColor": [1, 0.95, 0.8, 1], "frontLampsLightPosition":[0, 0.726, 1.388], "frontLampsShafts": [ { "position": [ 0.6, 0.245, 2.618], "scale": [2, 1.304, 1.402] }, { "position": [-0.6, 0.245, 2.618], "scale": [2, 1.304, 1.402] } ], "cargoStrapsHooks": [[0.6, 0.3, 0], [-0.6, 0.3, 0]], "lamps": [ { "front": true, "bulb": [ 0.59, 0.36, 1.74] }, { "front": true, "bulb": [-0.59, 0.36, 1.74] }, { "front": false, "bulb": [-0.66, 0.39, -2.10] }, { "front": false, "bulb": [ 0.66, 0.39, -2.10] } ] }, "hardpoints": [ { "index": 0, "position": [0, 1.52, -0.1] }, { "index": 1, "position": [0, 0.3, -1.4] }, { "index": 3, "position": [0, 10.225, 1.63] } ], "antennaPosition": [0.44, 0.515, -1.8] }