Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
LoopLagLimiter
Fixes late-loop lag: caps runaway Meat Hook pulls, dead orbs, post-teleporter waves and the physics catch-up spiral. Optional proc limits (covers modded item tiers) and a built-in lag profiler.
| Date uploaded | a day ago |
| Version | 1.0.0 |
| Download link | Videowiz92-LoopLagLimiter-1.0.0.zip |
| Downloads | 20 |
| Dependency string | Videowiz92-LoopLagLimiter-1.0.0 |
This mod requires the following mods to function
bbepis-BepInExPack
Unified BepInEx all-in-one modding pack - plugin framework, detour library
Preferred version: 5.4.2122README
LoopLagLimiter
Performance fixes for long, heavily looped Risk of Rain 2 runs, the kind where the game sinks to one frame every few seconds once the teleporter bosses spawn.
Every fix targets a specific runaway system found by profiling a real stage-45 run. No item's damage changes by default: LoopLagLimiter only removes work that can't affect the outcome, or that is pure overload. Everything is configurable in-game with Risk of Options (optional) or in the config file.
What it fixes (on by default)
| Fix | Problem it solves |
|---|---|
| Physics catch-up cap (0.1 s) | After a slow frame, Unity runs extra physics ticks to catch up, which makes the next frame slow too. In the test run, every bad frame ran 20 ticks. The cap turns that lag spiral into slow motion, but only when you are below ~10 FPS. |
| Meat Hook pull cap (25 per kind) | Sentient Meat Hook spawns a pull effect on every proc. Big builds stacked 300–800 of them, each searching for targets every tick (up to 1.1 s per frame). The oldest are removed first; hook damage is untouched. |
| Orbs with dead targets | Polylute, Meat Hook, vine and lightning orbs kept flying after their target died, and could even outlive the stage. They are now removed. |
| Camp director credit cap (3,000) | When the teleporter finishes, its leftover monster credits go to the stage's camp director. Deep into a loop that's hundreds of thousands of credits (525,196 in the test run), spent on an endless post-teleporter wave. |
| Exception spam guards | Resonance Disc beams hitting a blocking shield throw an error that cancels the whole beam and writes a full stack trace to the log every time. |
In the run this mod was built from, the worst frame went from 3.7 s to 1.5 s with only the first fixes in place. The camp director cap and the catch-up cap address most of what was left.
Optional limits (off by default)
These trade damage for frame rate. Turn them on only if fights are still too slow.
- Proc limits: "at most N per second" for Sentient Meat Hook, Polylute, Ukulele, Plasma Shrimp, Charged Perforator, AtG Missile, Sticky Bomb, Molten Perforator and Ceremonial Dagger, plus your own entries for any orb or projectile. Limits apply to what the proc creates, so modded copies of an item (e.g. ItemQualities' quality tiers) are covered too.
- Max alive projectiles per prefab: e.g. no more than 300 Sticky Bombs at once.
- Max visual effects per tick: visual only.
Diagnostics (off by default)
Turn on Enable diagnostics and restart. Whenever a frame takes over 250 ms, a report is written to
BepInEx/LoopLagLimiter/. It covers time spent in damage, procs, orbs, projectiles, effects, stat recalcs and directors, who
triggered them, and what exists at that moment. F10 turns on deep profiling (every component's update in the game and all
mods); F9 writes a report on demand. Useful for finding what is lagging your run.
Compatibility
- Doesn't reference the game's code directly, so a game update can only disable an individual fix (logged), not crash the mod.
- The limits act on the host; clients in multiplayer don't need special setup.
- Don't use with NoFrameSkip. The catch-up cap does the same thing. Or set "Max catch-up per frame" to -1 to leave it to NoFrameSkip.
- Works alongside ItemQualities; the proc limits cover its quality items.
- If the game ever sticks on a white screen at boot with this mod, set
Register Risk of Options page = falsein section "0. Troubleshooting" of the config and report it on GitHub.
Credits
- ProcLimiter by DrinkableWater (source): the idea of per-item proc cooldowns to fight late-game lag. ProcLimiter is deprecated and was built for game version 1.2.3. LoopLagLimiter's proc limits are a from-scratch reimplementation (no code reused) that works on current versions and covers modded item variants.
- NoFrameSkip by McAwesome (source, MIT): the idea of capping
Time.maximumDeltaTimeto stop the physics catch-up spiral. Reimplemented here; please support the original. - Risk of Options by Rune580: in-game settings page.
Made by Videowiz92.
CHANGELOG
1.2.0
- New: projectile fire-rate cap, on by default (30 per kind per physics tick, covers every item). Ghost Blades are kept at 30 alive by the game, so each new blade destroys the oldest; 4,960 were created and destroyed in one frame, freezing the game for 33 seconds. The alive cap couldn't catch that because only 30 ever existed.
- Fix: the "never block ally-spawning projectiles" check also matched projectiles that are themselves deployables (Ghost Blades), which exempted them from every cap. It now only matches projectiles that create a character (ally, minion, clone), and the log says which component matched.
- New: money overflow guard, on by default. Money stops at 2,147,483,647 instead of wrapping past ~4.29 billion back to near zero (and showing as negative on the HUD above ~2.15 billion).
- Fix: the money guard never ran in-game, because the game inlines the tiny GiveMoney method into its callers and skips the
hook. A new preloader patcher (
BepInEx/patchers/LoopLagLimiter.Patcher.dll) marks GiveMoney, the money setter and the price methods as non-inlinable before the game loads. Money is now also clamped in its setter and by a periodic backstop. - New: heavy-load mode (only below 15 FPS, so normal runs are untouched): gold nuggets from Ghor's Tome are paused, and item drops queue once 50 items are on the ground, dropping one at a time as items are picked up. Gold nuggets are also skipped whenever every player's money is maxed. While items are queued, a big red chat warning appears when a player is near a charged teleporter or portal, so nobody leaves items behind. Other physics pickups (Monster Tooth healing orbs, Bandolier ammo packs, buff pickups and modded quality variants) are paused under heavy load too, with their own setting. When heavy load starts (and every second while it lasts), the nuggets and pickups already on the ground are cleared too.
- Changed: the visual effect cap is now on by default at 75 per tick (purely visual; cut total stall time from 26 s to under 8 s in testing). It is a new setting, "Visual effects per tick limit", so 1.1.0 configs get 75 too; a non-zero value set under the old "Max visual effects per tick" is carried over.
- Changed: queued item drops keep the spacing they were dropped with (e.g. the teleporter's delay between boss items), and that spacing pauses while the ground is full, so picking up a pile of items no longer releases the backlog all at once.
- New: Sky Meadow falling rocks pause under heavy load, then ramp back from none to normal over 60 seconds once the game recovers.
- Fix: queued item drops left over when a run ends are discarded quietly instead of logging an error for each one.
- New: total projectile cap (Limits → Max alive projectiles total, 1000). Once that many projectiles exist together, kinds with 100+ alive stop firing until the total drops; smaller kinds (skills, rare items, enemy attacks) are unaffected.
- Config sections renumbered to match the settings page order: 0. Troubleshooting, 1. General, 2. Limits, 3. Heavy load, 4. Fixes, 5. Proc limits, 6. Diagnostics. Settings saved under the old section names are carried over automatically.
- New: price overflow guard, on by default. Prices that overflow into negatives (base cost times a huge loop difficulty multiplier) become 2,147,483,647, the same ceiling as money, so items stay buyable once money is maxed.
1.1.0
- New: Gasoline chain guard (on by default). Gasoline's explosion runs inside the death that triggered it, so a dense pack of low-health enemies (e.g. a Halcyon Shrine wave deep into a loop) could chain deep enough to crash the game with a stack overflow, freezing it completely. Past 20 levels, the next explosion is queued for the next physics tick; every explosion still happens.
- New: projectile cap, on by default (500 alive per kind, covers every item). A looped Halcyon Shrine fight had 10,577 Sticky Bombs alive at once. The old opt-in "Max alive projectiles per prefab" setting is replaced by "Max alive projectiles per kind".
- New: orb cap, on by default (300 in flight per kind, covers every item). The same fight had 1,500 Polylute orbs in flight.
- New: the credit cap now also covers the Halcyon Shrine's wave director (seen at 650,000+ credits).
- Fix: projectile counting is now correct even if the game recycles projectile objects, and a burst fired within one tick can no longer overshoot the cap.
- Safety: the pull cap only removes free-standing pull effects (never characters, allies, minions or deployables), and projectiles that spawn something (allies, minions, clones like Goobo Jr.'s) are never blocked by any cap or limit.
- New: Bundle of Fireworks proc limit (off by default). Fireworks combined with Pocket I.C.B.M. can flood the stage with rockets.
- README: new "How each mechanic works" section explaining every setting, its trade-off and default.
- README: diagnostics keys (F9/F10) only work after turning on "Enable diagnostics" and restarting.
1.0.0
- First release.
- On by default: physics catch-up cap, Meat Hook pull cap, removal of orbs with dead targets, camp director credit cap, exception spam guards.
- Optional: per-second proc limits, max alive projectiles per prefab, max visual effects per tick.
- Diagnostics mode with stall reports and deep profiling (off by default).
- Risk of Options settings page with icon (optional dependency).