You are viewing a potentially older version of this package. View all versions.
RockBreaker-ValheimBuildOptimization-0.5.4 icon

ValheimBuildOptimization

A Valheim BepInEx optimization plugin for large builds, featuring spatial renderer batching, fire and light culling, optional wear-and-tear calculation bypasses, and built-in performance diagnostics.

Date uploaded 2 weeks ago
Version 0.5.4
Download link RockBreaker-ValheimBuildOptimization-0.5.4.zip
Downloads 153
Dependency string RockBreaker-ValheimBuildOptimization-0.5.4

This mod requires the following mods to function

denikson-BepInExPack_Valheim-5.4.2333 icon
denikson-BepInExPack_Valheim

BepInEx pack for Valheim. Preconfigured with the correct entry point for mods and preferred defaults for the community.

Preferred version: 5.4.2333

README

Valheim Build Optimization

Valheim Build Optimization is a BepInEx client-side performance mod for bases.

During testing on a 24,000-instance base, average FPS increased from around 20 FPS to around 55 FPS.

That is an average gain of about 35 FPS, or roughly a 175% increase over the original average.

Results will vary depending on hardware, base layout, active effects, mod configuration, and other installed mods.

If you encounter any issues or have suggestions, please don’t hesitate to DM me on Discord: draco_alias

Its main job is to reduce the rendering, lighting, particle, structural, and optional diagnostic work caused by thousands of loaded build pieces. The mod is designed around targeted optimizations. Expensive systems are changed only when the mod can identify a reasonably safe case, and experimental systems have separate switches so they can remain completely dormant during normal play.

The project began as a build-piece profiler, so it also includes an optional in-game diagnostics window for measuring scene, rendering, physics, fire, batching, collider, script, and network activity.

Requirements

  • Valheim
  • BepInEx 5
  • A client running the mod

Install ValheimBuildOptimization.dll in:

Valheim/BepInEx/plugins/

Configuration is created in:

Valheim/BepInEx/config/valheim.buildpieceprofiler.cfg

The BepInEx Configuration Manager mod is recommended, but not required.

Recommended Starting Configuration

For ordinary use:

  • Enable fire optimization.
  • Use StaticLight fire mode.
  • Enable outside-camera and behind-geometry fire culling.
  • Enable clustered fire proxy lights.
  • Enable renderer batching for large static bases.
  • Enable wear-and-tear optimization only if you intentionally want support and weather wear disabled.
  • Leave shadow optimization, static component sleeping, collider clustering, network diagnostics, and automatic profiler polling off until testing them deliberately.

Existing configuration files keep their previous values after an update. Use Configuration Manager's Reset button if you want a setting to return to its new default.

Fire Optimization

Fire optimization works on supported fireplaces, torches, sconces, braziers, hearths, bonfires, and similar fire pieces.

Banana Explanation

If monkey put fire sticks in banana house, banana house warm, banana house pretty, monkey happy.

But monkey put many fire sticks. Maybe too many fire sticks. Fire sticks not lazy. Fire sticks wiggle flame, throw sparkle, make light, think about shadow, do tiny fire dance. Fire sticks eat FPS banana.

If monkey looking at fire, okay. Fire doing fire job. Monkey see pretty fire.

But if monkey not looking at fire, fire still working. Monkey on other side of house staring at stone wall, but fire sticks still dance like monkey watching. Computer still work. FPS banana still disappear.

Mod says, "Why fire work? Monkey no see fire."

So hidden fire goes sleepy. Big expensive light takes nap. Tiny cheap banana glow stays awake so room still look warm and not dead.

When monkey look back, fire wakes up fast. Fire wiggle again. Fire sparkle again. Fire says, "I was working. Promise."

Same banana house. Same pretty fire when monkey see it. Less invisible fire work when monkey no see it. More FPS banana for monkey.

Technical Explanation

The fire system discovers only Fireplace components whose piece names match a configurable known-fire allowlist and which contain both lights and particle systems. This avoids treating unrelated decorative effects as fire.

Each candidate is evaluated at a configurable interval rather than every frame. Visibility is determined using the main camera frustum. Optional occlusion testing uses budgeted non-allocating raycasts or spherecasts from the camera to the fire. Occlusion results are cached and only a limited number of fresh physics checks may occur during one optimizer update.

The optimizer uses grace periods in both directions:

  • A fire must remain hidden before optimization starts.
  • A fire must remain relevant before its original state is restored.

These delays reduce state cycling when the camera passes wall edges or the player turns rapidly.

When a fire enters an optimized state, the mod records:

  • original light enabled states and culling masks;
  • particle playback and emission states;
  • renderer shadow-casting modes;
  • enabled states of known light-flicker or light-LOD scripts.

The original fire lights are disabled and removed from rendering through their culling masks. Fire particle emission is disabled and existing particles are cleared. Known fire-light update scripts are paused so vanilla logic does not continually fight the optimized state.

When the fire becomes relevant again, recorded states are restored. The mod checks whether the source is still burning before relighting visual systems, which prevents extinguished fires from being incorrectly restored as lit.

StaticLight Mode

Banana Explanation

Monkey cannot see ten fire sticks behind wall.

Monkey only sees warm glow through doorway.

Ten fancy lights still do ten jobs. Ten lights eat FPS banana for one glow.

Mod says, "Monkey need glow, not ten tiny suns."

Hidden lights go sleepy. One simple banana lamp covers the group.

Room still cozy. Computer less sad. More FPS banana.

Technical Explanation

StaticLight disables hidden original fire lights and effects but preserves approximate illumination using shadowless proxy lights.

Proxy lights are pooled. They are reused instead of repeatedly created and destroyed, reducing managed allocations and Unity object churn.

When clustered proxy lights are enabled, hidden fires inside the same world-space cell contribute to one representative light. The cluster averages source position and color, combines intensity conservatively, uses the largest source range, and disables real-time shadows. Each cluster light is updated once per optimizer cycle.

This mode is intended to preserve the visual impression of illuminated rooms while reducing the number of dynamic lights, shadow calculations, flicker scripts, and active particle systems.

FullCull Mode

Banana Explanation

Fire hidden behind three stone walls.

Monkey see no flame. Monkey see no glow. Monkey see only rock.

Mod says, "Why fire dance? Monkey see nothing."

Whole fire show goes sleepy until monkey can see it again.

No wasted fire dance. More FPS banana.

Technical Explanation

FullCull disables hidden original lights, particle emission, fire particles, light-update scripts, and fire mesh shadow casting without creating a replacement light.

It provides the most aggressive fire reduction, but hidden rooms may become visibly darker through openings. StaticLight is the recommended visual-quality mode.

Spatial Renderer Batching

Banana Explanation

Without batching, monkey gives painter many tiny jobs.

"Paint wall one. Paint wall two. Paint wall three. Paint wall four."

Painter hears many orders. Computer gets tired. FPS banana gets eaten.

With batching, mod says, "These walls live together. Make one big paint job."

Monkey points at whole wall section and says:

"Paint this big wall chunk."

Same stones. Same building. Less yelling at painter. More FPS banana.

Technical Explanation

Renderer batching divides the world into configurable spatial cells. Eligible opaque, static build-piece renderers inside each cell are grouped by compatible rendering state and combined into generated meshes.

The system keeps original colliders and gameplay components. It disables only source renderers represented by a successful combined mesh.

Pieces are excluded when they are likely to change or require independent rendering. Examples include:

  • doors, portals, containers, crafting stations, and machines;
  • fireplaces, lights, and particle effects;
  • animated or skinned objects;
  • non-kinematic rigidbodies;
  • transparent or incompatible materials;
  • unsupported mesh layouts;
  • lightmapped renderers;
  • configured name-filter matches.

Compatible renderers are grouped by material, layer, shadow mode, probe settings, sorting state, and other rendering properties. Groups are split when they would exceed the configured vertex limit.

Piece discovery and cell rebuilding are budgeted across frames. Placement, destruction, damage, repair, and health changes mark only the affected spatial cell for delayed rebuilding. The delay coalesces rapid construction changes into fewer mesh rebuilds.

Highlighting a batched piece temporarily enables only that piece's original renderers instead of destroying and rebuilding the entire cell.

The system caches stable eligibility, renderer arrays, and LOD classification to avoid repeatedly scanning the same component hierarchies.

Renderer batching is currently the highest-impact optimization in very large static bases.

Shadow Optimization

Banana Explanation

Monkey squishes many walls into one big painting.

Painter happy. Computer happy.

But sun still remembers old walls.

"Wall one, make shadow. Wall two, make shadow. Wall three, make shadow."

Too many shadow chores. FPS banana gets nibbled.

Shadow optimizer tries to give sun fewer, simpler shadow shapes.

Good idea, but sun is picky. Sometimes sun no like banana math.

Feature is experimental, so it sleeps behind master switch until monkey says yes.

Technical Explanation

The shadow system is an experimental extension of renderer batching. It considers compatible opaque combined batches that still cast real-time shadows and attempts to replace several shadow casters with one shadow-only mesh.

Clusters are accepted only when they meet configurable requirements for:

  • minimum visible source batches;
  • minimum estimated shadow draw calls saved;
  • maximum total generated vertices;
  • maximum vertices per draw call saved;
  • maximum world-space bounds size.

Exact shadow meshes contain position and triangle data without unnecessary normals or visual-material data. Source mesh geometry may be cached while exact clusters are active.

An optional simplified structural mode represents configured walls and roofs with box-like shadow geometry. This can greatly reduce vertex cost, but may change shadow silhouettes.

Shadow optimization is disabled by default because exact shadow clusters can cost more geometry and culling precision than the draw calls they save. It should be tested separately from renderer batching.

Wear and Tear Optimization

Banana Explanation

Normally every building piece keeps asking:

"Am I supported? Is roof above me? Is rain touching me? Am I wet now? How about now?"

Many pieces ask many questions. Computer keeps answering. FPS banana gets chewed.

But monkey base has no collapse and no rain damage anyway.

Mod says, "Why ask about danger that no exist?"

Every piece gets permanent strong banana pillar and permanent invisible umbrella.

Piece feels safe. Piece stops asking. Computer gets quiet.

Same base. Less nervous wood. More FPS banana for monkey.

Technical Explanation

When enabled, the mod bypasses selected WearNTear methods:

  • support updates are skipped;
  • support queries return a configurable high synthetic value;
  • support checks always succeed;
  • cover updates are skipped;
  • normal and ash roof checks succeed;
  • wetness checks return false.

The system intentionally does not bypass:

  • health;
  • direct damage;
  • repairs;
  • destruction;
  • persistence;
  • ordinary network state.

This changes gameplay. Structures effectively have full support, and rain or weather does not make affected pieces wet. Enable it only when that behavior is desired.

Static Component Sleeping

Banana Explanation

Some decorations look still, but tiny monkey inside keeps turning wheel every frame.

Decoration no move. Decoration no change. Tiny monkey still work. FPS banana gets nibbled.

Sleeper wants to tell approved tiny monkey:

"Take nap. Wake up only when building changes."

Good for boring decorations.

But mod must be careful. Some tiny monkeys look decorative, but secretly run machine. Wrong monkey takes nap, machine breaks.

So feature is cautious and experimental. Only approved tiny monkeys may sleep.

Technical Explanation

This system profiles build-piece MonoBehaviour types that implement Update, LateUpdate, or FixedUpdate.

Sleeping is restricted by:

  • an explicit exact-type whitelist;
  • a gameplay-script denylist;
  • structural-piece requirements;
  • rigidbody and interaction safety checks.

Approved components may be disabled after a grace period. Placement, damage, repair, health changes, or highlighting restores them and schedules another sleep attempt.

The system currently has no broadly proven default target in vanilla Valheim, so its master switch, profiling, and sleeping are disabled by default. When the master switch is off, it performs no discovery or event work.

Compound Collider Clustering

Banana Explanation

Base floor has ten thousand tiny invisible boxes.

Boxes tell monkey where feet can stand. Boxes also tell hammer which floor piece monkey is pointing at.

Collider clustering says, "Why many tiny boxes in straight line? Make one long banana box."

Fewer boxes means less work. Computer happy.

But monkey hammer is picky. Monkey selection ray still needs to know exact floor piece that got hit.

If wrong box answers, monkey bonks wrong floor. Bad banana.

So feature is clever, risky, and currently experimental.

Technical Explanation

The collider system searches for enabled, non-trigger, static BoxCollider components on eligible structural pieces.

It excludes:

  • colliders attached to moving rigidbodies;
  • interactive and animated pieces;
  • lights and effects;
  • non-box collider types;
  • configured name-filter matches.

Compatible boxes are grouped by layer and physics material. Only world-axis-aligned, collinear boxes with matching cross-sections may merge.

Original colliders remain active near the player. Beyond the configured activation distance, eligible cells may enable merged colliders and disable represented originals. A hysteresis gap separates activation and restoration distances.

Generated clusters include a damage proxy that maps a hit back to the nearest original source piece. This cannot perfectly preserve every possible collider lookup or mod interaction.

The system has measured as a performance loss in current large-base tests. It remains available for development but is disabled behind a master switch.

Network Activity Diagnostics

Banana Explanation

Monkey wants to know which machines keep sending banana paperwork.

Profiler watches paperwork. Profiler counts who writes most forms, who yells most, and who keeps bothering server.

Profiler does not stop paperwork. Profiler only spies and makes report.

Useful when monkey is testing. Not useful for normal banana life.

Leave spy monkey home unless monkey is hunting network problem.

Technical Explanation

The network diagnostics system maps build-piece ZNetView components to their ZDO records and can measure:

  • attempted and changed ZDO writes;
  • writes deduplicated by Valheim because the value was unchanged;
  • data revision changes;
  • ownership changes;
  • build-piece RPC calls;
  • active static and dynamic writers;
  • global sent and received ZDO counters;
  • the client change queue.

Global write and RPC hooks are installed dynamically only while both the network master switch and profiling option are enabled. They are removed when the system is disabled.

This system does not currently throttle networking. It is a diagnostic foundation for future work and is disabled by default.

Profiler

Banana Explanation

Monkey opens clipboard, counts everything, writes numbers, then closes clipboard.

Counting helps monkey see what is eating FPS banana.

But counting giant base also takes work. Clipboard monkey is not free.

Use when testing. Do not ask monkey to recount every second unless monkey actually needs numbers.

Technical Explanation

Press the configured profiler key, F7 by default, to open the in-game window when the profiler is enabled.

The window is organized into collapsed sections:

  • global scene;
  • global rendering;
  • global physics;
  • global effects;
  • build-piece rendering;
  • build-piece physics;
  • build-piece effects;
  • fire optimization;
  • renderer batching;
  • shadow optimization;
  • static component sleeping;
  • collider clustering;
  • network activity;
  • top light offenders.

Hover any section or statistic for a plain-language explanation.

Poll now performs a synchronous full snapshot. It scans loaded objects and build-piece child components, so a huge world may briefly pause. Automatic polling is disabled by default and is automatically suppressed above the built-in large-world safety limit.

The profiler and automatic polling are both disabled by default for normal gameplay.

Compatibility and Safety

  • The mod is primarily client-side, but some optimizations intentionally change local simulation behavior.
  • Renderer batching preserves original colliders and gameplay components.
  • Fire optimization restores recorded visual states when a fire becomes relevant.
  • Wear-and-tear optimization intentionally changes structural support and weather-wear gameplay.
  • Experimental systems are separately gated and disabled by default.
  • Mods that replace fire prefabs, materials, piece hierarchies, or collider behavior may require name-list or safety-list adjustments.

Before testing an experimental feature, back up important worlds and change one system at a time. Record FPS and frame time from the same location, camera direction, weather, and graphics settings.

Troubleshooting

The profiler does not open

Enable Profiler.EnableProfiler, then press the configured profiler key.

Old defaults still appear enabled

BepInEx preserves values already written to the configuration file. Reset the individual setting in Configuration Manager, or remove the configuration file while the game is closed to regenerate every default.

A modded fire is not optimized

Add a unique fragment of its internal prefab or object name to Fire Discovery.KnownFirePieceNameTokens. The object must also use a Fireplace component and contain both a light and a particle system.

A visible fire remains optimized too long

Reduce the fire restore grace period or occlusion cache duration. Very low values can make state changes more noticeable.

Building visuals change after enabling batching

Add a unique internal name fragment to Renderer Batching.ExcludedPieceNameTokens, then reload or toggle renderer batching.

FPS decreases after enabling an experimental system

Disable that system's EnableSystem master switch. Collider clustering, shadow optimization, static component sleeping, and network diagnostics are development foundations, not recommended default optimizations.