Repository navigation
Levels with SceneTools
The game has no level editor (October 2026). Levels are Unity scenes made in the developer's SceneTools project and exported as .sobj bundles, which a mod folder carries like any other file. The madnesswright-scenes skill walks through that project, lints the saved scene with mpn.py scene-lint, and runs the build, deploy and playtest loop. Its rules come from the official SceneTools Overview and Event System Overview, read on 2026-10-17 (madnesswright-scenes RESEARCH.md).
- The game on
releasebetawith a fresh backup (Getting started). - The project from github.com/MPN-Modders/MPN_SceneTools. It has no license file, so its files must not be redistributed; madnesswright copies none of them. Pull it again before a session, since commits land every few weeks.
- Unity 2019.2.6f1 exactly, installed through Unity Hub from the download archive. You install it; the agent does not.
- Copy
Assets/Scenes/SamplePlayground_PG.unityorSampleSiegeArena.unityrather than editing the samples.
- A Playground scene: its name ends in
_PG, and it shows in the Playground scene list (the terminal by the control room door). The fastest test loop, so the skill builds here first even for a stage. - A custom stage in a campaign: needs a Stage card and a Campaign card, with Story rules (no Siege or Infiltration). A stage with no valid
SceneNameor noRequiredCharactersis dropped by the game. - An Arena Siege or Infiltration stage: as of August 2026 a custom arena stage can only replace an existing one, and the tools are marked "testing".
The card fields for stages, campaigns, cutscenes, events and missions are in the skill's references/stages-and-campaigns.md, and the objects, layers and rules in references/scenetools-rules.md.
- Block out the room: drag in
Room_Layout, click SYNCH VISUALS, never rotate a room. Floors get Tag Floor, Layer Terrain and Static. Exactly onePlayer_Start, under the room'sCharactersobject, and at least one waypoint per room. - Plan encounters before placing enemies. The skill writes
LEVEL-PLAN.mdinto the mod folder, one line per room, so the playtest has something to check against. - Save the scene (Unity writes it as text) and run
mpn.py scene-linton it. - Give the scene an Asset Label, then build from the menu Madness, AssetBundle,
>> Build (Compressed) *RECOMMENDED*. The.sobjlands in%USERPROFILE%\AppData\LocalLow\Gibbing Tree\Madness Project Nexus SceneTools\SceneObjs\, andmpn.py wherelists the newest undertool_outputs.scenetools. - Copy the
.sobjinto the mod folder with any Stage, Campaign, Event or Cutscene cards, thencheck-modanddeploy. - You playtest against the checklist the skill fills in (spawn, camera borders, each door, enemy pathing, each encounter clearable), then
mpn.py log. One change at a time.
A headless build through Unity.exe -batchmode is described in the skill but unverified: no 2019.2.6f1 editor was available to test it.
It reads the .unity file and its .meta, finds the SceneTools project by walking up to the folder holding Assets and ProjectSettings (or takes --project), and names prefab instances from the project's .prefab.meta files. Rule ids come from the official docs.
| Id | Rule | Reported as |
|---|---|---|
| S01 | exactly one Player_Start in the scene |
error |
| S02 |
Player_Start parented to the room's Characters
|
error |
| S03 | rooms never rotated | error |
| S04 |
Zone_Camera not rotated |
error |
| S05 |
Zone_Camera under the room's Waypoints
|
error |
| S06 | at most one SceneRules
|
error |
| S07 |
SceneRules in the scene root |
warning |
| S08 | objects tagged Floor on Layer Terrain | error |
| S09 | objects tagged Floor marked Static | error |
| S10 | no camera other than Dev_Cam (delete the default Main Camera) |
warning |
| S11 | no default Directional Light
|
warning |
| S12 | at most 4 active lights (3 on low quality) | warning |
| S13 | the scene has an Asset Label, or >> Build skips it |
error |
It also warns when it finds no Room_Layout instance or no object tagged Floor, and reports in info.playground_listed whether the name ends in _PG. A missing _PG is a note, not a problem: stage-only scenes need not show in the Playground.
The limits, from the code: it sees the scene file only, not in-game behaviour, pathing or event logic. Floors inside room prefabs are not checked, unpacked rooms are not detected, and S12 counts every light in the scene file against four per room rather than the lights active at one time.
The repository's fixture project (tests/fixtures/scene-project, synthetic) has two scenes. Arena_PG.unity has no Player_Start and puts its Zone_Camera under Characters:
python mpn.py scene-lint scene-project/Assets/Scenes/Arena_PG.unity{
"scene": "scene-project\\Assets\\Scenes\\Arena_PG.unity",
"project": "scene-project",
"errors": [
"S01 every scene needs exactly one Player_Start; found 0",
"S05 Zone_Camera must be parented to its room's Waypoints object or it is not detected; parent is Characters"
],
"warnings": [],
"info": {
"prefab_counts": {
"Room_Layout": 1,
"SceneRules": 1,
"Zone_Camera": 1
},
"rooms": 1,
"floors_tagged": 1,
"lights_in_scene_file": 0,
"asset_label": "arena_pg",
"playground_listed": true
}
}
Exit code 0.
Warehouse_PG.unity has a rotated room and an empty Asset Label:
python mpn.py scene-lint scene-project/Assets/Scenes/Warehouse_PG.unity{
"scene": "scene-project\\Assets\\Scenes\\Warehouse_PG.unity",
"project": "scene-project",
"errors": [
"S03 room Room_Layout is rotated; rooms must never be rotated",
"S13 the scene has no Asset Label (AssetBundle name); >> Build will not export it"
],
"warnings": [],
"info": {
"prefab_counts": {
"Player_Start": 1,
"Room_Layout": 1,
"SceneRules": 1,
"Zone_Camera": 1
},
"rooms": 1,
"floors_tagged": 1,
"lights_in_scene_file": 0,
"asset_label": null,
"playground_listed": true
}
}
Exit code 0.
Like every command, scene-lint exits 0 even with errors. Put --strict before the command name to exit 1 when there are errors:
python mpn.py --strict scene-lint scene-project/Assets/Scenes/Warehouse_PG.unity{
"scene": "scene-project\\Assets\\Scenes\\Warehouse_PG.unity",
"project": "scene-project",
"errors": [
"S03 room Room_Layout is rotated; rooms must never be rotated",
"S13 the scene has no Asset Label (AssetBundle name); >> Build will not export it"
],
"warnings": [],
"info": {
"prefab_counts": {
"Player_Start": 1,
"Room_Layout": 1,
"SceneRules": 1,
"Zone_Camera": 1
},
"rooms": 1,
"floors_tagged": 1,
"lights_in_scene_file": 0,
"asset_label": null,
"playground_listed": true
}
}
Exit code 1.
A scene saved in binary is refused with the setting to change:
python mpn.py scene-lint Binary.unity{
"scene": "Binary.unity",
"errors": [
"scene is binary; set Edit > Project Settings > Editor > Asset Serialization to Force Text"
],
"warnings": [],
"info": {}
}
Exit code 0.
On Linux and macOS the scene path prints with forward slashes.
This wiki describes madnesswright 0.1.2 (tag v0.1.2) and was last updated on 2026-10-18. The plugin is MIT licensed. Report problems in the issues. Download: madnesswright 0.1.2.
Using it
- Getting started
- Mods and MadCards
- Levels with SceneTools
- Assets and Harmony
- The helper
- Troubleshooting
- FAQ
The releases
Contributing
Elsewhere