ButterNet Multiplayer Voxel

Installation & Setup

Requirements

Unreal Engine 5.8. Blueprint or C++ project. The plugin contains three modules and needs nothing else: ButterNetRuntimeVoxels (volumes, editing, meshing, replication, persistence, debris), ButterNetVoxelsLandscape (terrain host for landscapes), and ButterNetVoxelsEditor (the Voxel Sculpt editor mode).

Install the plugin

  1. Install from Fab

    Add the plugin to your library and install it to your engine version from the Epic Games Launcher.

  2. Enable the plugin

    Edit → Plugins → ButterNet Voxels, then restart the editor.

Optional: Iris replication

The plugin supports both network drivers. To run on Iris add to [SystemSettings] in Config/DefaultEngine.ini:

net.Iris.UseIrisReplication=1
net.SubObjects.DefaultUseSubObjectReplicationList=1

Iris refuses actors that replicate subobjects the legacy way, so the second line is required. Remove both lines to return to the legacy driver.

Concepts

TermMeaning
VolumeAn AVoxelVolumeActor placed in a level or spawned at runtime. It owns a box of chunks.
Chunk32 × 32 × 32 voxels. Unedited chunks regenerate from the generator on demand and cost no memory; edited chunks hold 64 KB.
Voxel sizeEdge length of one voxel in centimetres, per definition. 50 cm suits terrain; 20 cm suits detailed structures.
DefinitionA VoxelVolumeDefinition data asset holding every setting. Several volumes can share one.
DensityA signed distance stored per voxel. Negative is solid. Surfaces are smooth because the mesh interpolates between voxels.
Material indexOne byte per voxel, 0 = air. It reaches your material as red vertex colour × 255.
ModeBlob or Terrain — where the volume's baseline voxels come from. See Volume modes.
Edit opA quantised brush application. Ops are integers end to end, so every machine that applies the same op gets the same voxels.

Quick start

A diggable blob in five steps:

  1. Create a definition

    Content Browser → Add → Miscellaneous → Data Asset → VoxelVolumeDefinition. Name it DA_Ground.

  2. Configure the generator

    Set Generator to Noise Terrain, add one Height Layer (Wavelength 128, Amplitude 20) and set Render Material to any material.

  3. Place a volume

    Drag VoxelVolumeActor from Place Actors into the level and set its Definition to DA_Ground. The terrain appears in the viewport.

  4. Create brush presets

    Create a VoxelBrushPreset named DA_Dig (Mode Subtract, Radius 150) and another DA_Fill (Mode Add).

  5. Wire input

    In your PlayerController, on a key press call Get World Subsystem (ButterNetVoxelSubsystem) → Request Edit From View with Controller = Self, Brush = DA_Dig, Reach = 600, Push Outward = false. For fill use DA_Fill with Push Outward = true so the sphere sits on the surface rather than inside it.

Play. Digging works in standalone, listen server and client sessions without further work; the subsystem routes client requests through a replicated player component that the plugin attaches at login.

Volume definition

All settings live on the VoxelVolumeDefinition asset unless stated otherwise.

SettingMeaning
Volume
ModeBlob or Terrain. See Volume modes.
Voxel Size CmEdge length of one voxel. Smaller = more detail, more memory and meshing time (cost grows with the cube).
Bounds Min/Max ChunkInclusive chunk coordinates the volume covers. 32 voxels per chunk, so at 50 cm a chunk is 16 m.
GeneratorBaseline shape for Blob volumes. See Generators.
Material SetOptional VoxelMaterialSet asset. See Material set & authorizer.
Terrain (Terrain mode only)
Terrain Surface MaterialMaterial index of the top layer of dug ground.
Terrain Surface Depth VoxelsVoxels below the surface that keep the surface material. Default 3.
Terrain Subsurface MaterialMaterial index below that.
Terrain Hide ModeMaterial Mask (per-column holes; needs MF_VoxelHoleMask in the landscape material), Hide Landscape Components (whole components hidden; no material changes), or None (landscape stays visible; collision only).
Carve Host CollisionLower the landscape collision under dug columns so the voxel mesh owns collision there.
Top-Down Mode
Enable Top-Down ModeCuts away cave roofs above the local player for overhead cameras. Gates a further sixteen settings. See Top-Down Mode.
Rendering
Render MaterialApplied to every chunk mesh.
Meshing ModeSurface Nets (smooth) or Dual Contouring (sharp edges; best with static-mesh generators).
Replication
ReplicateOff makes the volume local to each machine.
Max Edit Range CmServer rejects edits further than this from the player. 0 disables.
Max Ops Per Second Per PlayerServer-side rate limit.
Snapshot Bytes Per SecondBandwidth cap for a client catching up from snapshots.
Persistence
PersistLoad on start, save on change. Needs a key.
Persistence KeyIdentifies the saved state. A placed actor can override it.
Auto Save Debounce SecondsQuiet time after the last edit before a save.
Performance & LOD
Enable LODDistant chunks mesh at 2× and 4× cell size on clients and standalone.
Far Distance CmBeyond this, chunks batch per region into one mesh.
Server Meshes Collision OnlyDedicated servers skip render data entirely.
Debris
Enable DebrisDisconnected pieces break off as physics actors after a dig.
Max Debris VoxelsLargest piece per axis that can break off; bigger pieces stay attached.

On the placed actor: Definition, optional Persistence Key Override, Terrain Host Actor for Terrain volumes, Preview In Editor, and buttons to refresh preview or clear authored state.

Volume modes: Blob vs Terrain

Every volume is one of two modes, set by Mode on the definition. The choice decides where the baseline voxels come from, when anything renders, and whether you can sculpt it in the editor. Everything else — editing, replication, persistence, debris — works the same either way.

BlobTerrain
Where the voxels come fromA generator on the definition.A terrain host — a landscape — sampled lazily.
Needs a generatorYes.No. The host is the baseline.
Needs a landscapeNo. It sits on whatever ground exists.Yes, set as Terrain Host Actor on the placed actor.
When it rendersImmediately, as a finite shape.Nothing until the first dig; then per edited column.
Effect on the landscapeNone.Hides the host surface and lowers its collision under dug columns.
Sculpt in the editorYes, with Voxel Sculpt mode.No. Terrain volumes are edited in play.
Typical useAsteroids, ore bodies, ruins, walls, destructible structures.Open-world digging, tunnels and mines into existing terrain.

Choosing between them

Pick Blob when the shape is the thing — something you author, place and let players carve. It is self-contained, it shows up in the editor viewport, and there is nothing to configure beyond the generator.

Pick Terrain when players should dig into ground that already exists. It costs nothing until someone digs, because untouched columns are never meshed — but it needs a landscape underneath, and how the landscape surface gets hidden is a decision with real setup behind it. See Terrain mode and landscapes.

The two mix freely in one level. A Terrain volume over the landscape for digging, Blob volumes for the ore veins inside it, is a normal arrangement.

Generators

Set on the definition's Generator. All generators are deterministic: the same settings give the same voxels on every machine. Untouched chunks regenerate from the generator; edited chunks are baseline plus replayed ops.

There are four: Noise Terrain, Spline, Static Mesh and Primitive. They all fill a Blob volume — a finite shape that sits on top of whatever ground already exists. A Terrain volume is different: it has no generator at all and takes its baseline from a landscape instead. See Terrain mode and landscapes.

Noise Terrain

Height-map terrain from layered gradient noise, with optional caves. Use it for standalone diggable islands and cave systems that do not need a landscape underneath.

  1. Set the definition mode to Blob

    Then set Generator to Noise Terrain.

  2. Place the ground

    Set Base Height Voxels to where the surface should sit, measured in voxels from the volume origin. Size the volume's chunk bounds so the terrain and its caves fit inside — content outside the bounds is cut off, and a warning is logged with the exact range.

  3. Add height layers

    Start with two entries in Height Layers: a long wavelength for hills, a short one for detail. Each layer carries its own seed, so changing one reshapes that layer alone.

  4. Set the materials

    Surface Material and Subsurface Material are indices into the volume's material set, with Surface Depth Voxels deciding where one becomes the other.

  5. Add caves if you want them

    Set Cave Mode, then tune Cave Threshold and Cave Min Depth Voxels.

SettingMeaning
Base Height VoxelsGround level before noise, in voxels from the volume origin.
Height LayersLayers summed into the height map: wavelength, amplitude, octaves, persistence, seed. A long wavelength for hills plus a short one for detail is a good start.
Surface MaterialMaterial index of the top layer.
Surface Depth VoxelsVoxels below the surface that use the surface material before switching to subsurface.
Subsurface MaterialMaterial index below the surface layer.
Caves
Cave ModeNone; Noise (3D noise tunnels); Random (discrete pockets per cell).
Cave ThresholdNoise mode: how much rock becomes air. Lower = more caves.
Cave Min Depth VoxelsCaves never open closer to the surface than this.

The volume exposes placed pockets through Get Caves, Get Cave Count and Find Nearest Cave for spawning loot or enemies.

Spline

Extrudes a closed loop you draw in the viewport into a solid column between two heights. Use it for walls, plateaus, moats and arenas — any footprint easier to draw than to describe numerically.

  1. Set the generator

    On a Blob definition, set Generator to Spline.

  2. Add the spline component

    Add a VoxelSplineComponent to the VoxelVolumeActor. It seeds a rectangle inside the volume bounds the first time it is enabled, so you always start from something visible.

  3. Shape the loop

    Edit Control Points Cm on the component, or drag the points in the viewport. Points are in the volume's local centimetres and the loop always closes back to the first point. Z is ignored — the footprint is XY only, and height comes from the two settings below.

  4. Set the height range

    Bottom Voxels and Top Voxels are the inclusive extent of the extruded column, in voxels from the volume origin.

  5. Choose which side is solid

    Fill Mode decides whether the inside of the loop is rock or air. Fill Inside gives a mesa; Fill Outside gives a pit or an arena floor with walls around it.

SettingMeaning
Control Points CmOn the VoxelSplineComponent, not the generator. XY footprint in the volume's local centimetres; Z is ignored.
Samples Per SegmentTessellation between control points, 2–64 (default 8). Raise it for smooth curves, lower it for hard polygonal shapes.
Fill ModeFill Inside — solid inside the loop, air outside. Fill Outside — air inside, solid outside.
Bottom VoxelsBottom of the extruded column, in voxels from the volume origin. Inclusive.
Top VoxelsTop of the extruded column, in voxels from the volume origin. Inclusive.
MaterialMaterial index given to every solid voxel.

The loop is tessellated once when the generator prepares, so control point changes take effect on the next regeneration rather than per frame.

Static Mesh

Voxelises a closed static mesh at runtime. Use it to turn authored geometry — a castle, a statue, a rock formation — into destructible voxels.

  1. Enable Allow CPU Access on the mesh

    Open the static mesh and tick Allow CPU Access. Do this first: without it the generator produces nothing in a packaged build. See the warning below.

  2. Set the generator

    On a Blob definition, set Generator to Static Mesh and assign the mesh.

  3. Place the mesh in the volume

    Use Mesh Transform to position and scale it, in centimetres, relative to the volume origin.

  4. Size the volume to fit

    The volume's bounds must contain the mesh. When they do not the content is cut off, and a warning is logged naming the exact chunk range needed.

  5. Check the voxel size against wall thickness

    Walls thinner than two voxels disappear. Lower the voxel size or thicken the source geometry.

SettingMeaning
MeshClosed static mesh to voxelise. Requires Allow CPU Access in cooked builds.
Mesh TransformPlacement of the mesh inside the volume, in centimetres.
MaterialMaterial index written into solid voxels.
Narrow Band VoxelsDistance from the surface over which exact signed distances are computed.

Static meshes need Allow CPU Access

The generator reads the mesh's vertex and index buffers directly. In the editor those always exist, but a cooked build discards the CPU copy once the mesh is uploaded to the GPU unless Allow CPU Access is ticked. Miss it and the volume works perfectly in PIE and generates nothing in a packaged build — no mesh, no collision, and no error a player would ever see.

Set it on every mesh you voxelise: open the static mesh, and under Details → General Settings tick Allow CPU Access. It keeps a copy of the mesh in memory, which is why it is off by default.

If a mesh volume comes up empty in a packaged build, search the log for has no CPU-accessible vertex data — the generator names the offending mesh. Shipping builds suppress logging, so use a Development package when diagnosing this.

Primitive

One sphere or box by centre, radius or half extents, and material. Useful for tests and for a floor under a sculpted volume.

Terrain mode and landscapes

A Terrain volume takes its ground from a terrain host. Place a VoxelVolumeActor over a landscape, give it a definition whose Mode is Terrain, and it samples the landscape heights on start. Nothing renders until the first dig; from then on each edited column renders as voxels, and the landscape is hidden and its collision lowered under that column.

  1. Create a terrain definition

    Set surface and subsurface materials and the Render Material for the voxel ground.

  2. Choose a hide mode

    Set Terrain Hide Mode on the definition. This controls how the landscape surface is hidden where voxels take over — it is separate from collision carving, which runs for every mode except None when Carve Host Collision is on. See the table below.

  3. Align and size

    Place the volume on a multiple of the voxel size so column edges line up with the hole mask. Size chunk bounds to the height range players can reach.

Terrain Hide ModeNeeds MF_VoxelHoleMask?What happens when you dig
Material Mask (default)YesThe host paints a runtime hole texture per dug column. The landscape material must read VoxelHoleMask through MF_VoxelHoleMask (Opacity Mask, blend Masked) or holes will not appear visually.
Hide Landscape ComponentsNoWhole landscape components (~63 m) are hidden on the first dig inside that component. No landscape material changes. Good default for demos and prototypes.
NoneNoThe landscape stays fully visible; only collision is lowered under dug columns. Use when you want the host surface to remain for rendering.

Digging can work without MF_VoxelHoleMask

If holes look fine but you never added the material function, check Terrain Hide Mode. With Hide Landscape Components, the plugin hides whole landscape components — no material setup required. Voxel meshes and carved collision still work in every mode, so gameplay can feel correct even when the landscape is not masked. With Material Mask but no MF_VoxelHoleMask, the host still updates the mask texture at runtime, but the landscape material ignores it — you may see z-fighting or landscape geometry inside tunnels.

MF_VoxelHoleMask (Material Mask mode only)

Only required when Terrain Hide Mode is Material Mask. The landscape host writes a runtime hole texture per dug column; your landscape material must read it through the plugin's material function:

  1. Open the function

    In the Content Browser: Plugins → ButterNet Voxels Content → Materials → MF_VoxelHoleMask.

  2. Add it to the landscape material

    Drop MF_VoxelHoleMask into the landscape material graph and connect its output to Opacity Mask.

  3. Set blend mode

    On the landscape material, set Blend Mode to Masked so clipped pixels are discarded rather than blended.

  4. Combine with an existing visibility mask

    If the material already uses a Landscape Visibility Mask, multiply the two masks together before Opacity Mask. Either order works; both must be 1 for the surface to show.

The function expects two texture parameters the host fills at runtime: VoxelHoleMask (the hole texture) and VoxelHoleMaskRect (world-space origin and UV scale). You do not assign these yourself — the landscape host creates dynamic material instances on the landscape and pushes updated values as players dig.

Mask resolution comes from Project Settings → Plugins → ButterNet Voxels → Hole Mask Texel Cm (default 100 cm per texel). Smaller texels give sharper hole edges and a larger texture. The ground is hidden only once the column's voxel meshes exist, so nothing shows through on a fresh dig.

The voxel mesh cannot use a landscape material directly. Put the ground appearance (triplanar textures, colour, roughness) in one material function and use it from both the landscape material and the voxel Render Material. The voxel material reads the material index from the red vertex colour channel.

Landscape grass and foliage

Grass and foliage are not removed over holes. Listen for On Voxels Removed and clear them in the game.

Top-Down Mode

For games with a fixed overhead or isometric camera, where a cave roof would otherwise hide the player. When the local player is under solid ground, the volume re-meshes the chunks above them with the roof cut away, so the excavation is visible from outside.

It is client-side and purely visual. Nothing replicates, collision is untouched, and other players see the volume completely unchanged. A dedicated server skips it entirely — it has no camera and nothing to hide.

Setup

  1. Enable it on the definition

    Tick Enable Top-Down Mode. Every other Top-Down setting stays hidden until you do.

  2. Assign a floor material

    Set Top Down Floor Material if you want a floor plane under the cutaway. Leaving it empty is valid and simply disables that layer.

  3. Set the floor height

    Top Down Floor Offset Cm is measured from the volume actor's origin, negative for down — not from the terrain surface.

  4. Play

    There is no code to write. The volume creates and drives the component itself on BeginPlay whenever the definition asks for it.

That is the whole setup. Everything else is tuning.

What counts as a cave

A voxel is treated as carved when it is solid in the baseline and air now — that is, a player dug it. Caves the generator produced are solid-to-air in the baseline too, so they keep their roof and stay dark. That distinction is deliberate: it is what stops procedural cave systems from being unroofed across the whole map.

Writing the floor material

The floor is a flat authored plane, not a surface traced from the terrain. Its height comes from Top Down Floor Offset Cm and nothing else. It is built by hand and carries no UVs and no tangents, which constrains the material:

M_TopDownCaveFloor in the plugin's demo content is a working example of all three. Its EdgeNoiseStrength parameter and the edge Noise node's Scale control how far the perimeter wanders — those are material parameters, not definition settings.

Entering and leaving

The transition is not a blend. The cut height animates: it starts at the ground surface, where it removes nothing, and slides down to its final height, re-meshing at each of Top Down Fade Steps positions. Every intermediate frame is ordinary opaque geometry, so nothing is ever dithered, sorted or drawn twice. Meshing runs on the worker pool, so more steps costs throughput rather than hitching.

Settings

SettingMeaning
Enable Top-Down ModeTurns the feature on for volumes using this definition. Gates every setting below.
The cut
Top Down Reveal Radius CmHow far from the pawn the reveal reaches. Default 2500.
Top Down Ceiling Drop CmHow far below the topmost carved voxel the cut sits. Default 100.
Top Down Chunks Per TickChunks built per frame during a rebuild pass. Default 1.
Transition
Top Down Fade StepsDiscrete steps the cut recedes in. Higher is smoother and costs one re-mesh per chunk per step. Default 16.
Top Down Fade In SecondsEntering. Default 0.35.
Top Down Fade Out SecondsLeaving. Default 0.6.
Top Down Fade CurveEasing curve over 0..1. Empty is linear.
Floor plane
Top Down Floor MaterialMaterial for the floor plane. Empty disables the floor layer entirely.
Top Down Floor Offset CmFloor height, in centimetres from the volume actor's origin. Negative is down. Default 0.
Top Down Floor Edge Fade CmWidth of the band the material cuts the floor's perimeter within. Default 300.
Scanning
Top Down Query IntervalSeconds between sightline probes. Default 0.1.
Top Down Scan ResolutionCap on the scan grid, in columns square. Default 128.
Top Down Scan Recentre CmHow far the pawn moves before a full rescan. Default 500.
Top Down Scan Rows Per TickScan rows processed per frame. Default 16.
Top Down Scan Depth Below CmHow far below the pawn columns are searched. Default 1500.
Top Down Scan Height Above CmHow far above. Default 2000.

Reacting to it in Blueprint

The voxel subsystem exposes two client-side events: On Local Player Entered Cave and On Local Player Exited Cave, each passing the volume involved. Useful for swapping ambience, post-process or music. They never fire on a dedicated server.

Five console variables drive and diagnose this feature, including outlines for the carved chunks and the columns the scan believes were dug. See Debug commands.

If Top-Down Mode does nothing

The definition needs Enable Top-Down Mode ticked — the component is created on BeginPlay only when it is set. Check bnv.TopDown.Enabled is 1, and remember a dedicated server skips the feature by design.

If the floor is nowhere to be seen, Top Down Floor Offset Cm is measured from the volume actor's origin, not the terrain surface — on a volume whose origin sits well above or below the ground, the default of 0 can put the plane somewhere unhelpful.

Material set & authorizer

Voxels store a compact material index (one byte, 0 = air). A VoxelMaterialSet data asset is an optional lookup table that gives those indices names, tool/yield ids and a gameplay tag for your Blueprint or C++ logic. Generators, terrain layers and brush presets still use raw indices; the set is how your game interprets them.

The material set does not affect rendering. Visuals come from Render Material on the definition and the index in the red vertex colour channel (index × 255). The set is for loot, effects, tool rules and anything else your game reads after an edit or query.

Creating a material set

  1. Create the asset

    Content Browser → Add → Miscellaneous → Data Asset → VoxelMaterialSet. Name it (for example DA_VoxelMaterials).

  2. Fill the entries

    Array slot N describes material index N. Leave index 0 as an air placeholder. Match the indices your generator and brushes use (surface material 1, subsurface 2, and so on).

  3. Assign on the definition

    Set Material Set on the VoxelVolumeDefinition. Several volumes can share one set.

Entry fieldMeaning
NameLookup string for Find Material. Not shown in the world.
HardnessMultiplier on how much effort an edit needs. Your authorizer or yield logic reads this; the plugin does not enforce it.
Required Tool IdFName id the player's equipped tool must match before an edit is allowed. Checked in your authorizer, not by the plugin.
Yield IdFName id for what removing this material produces — inventory, loot tables, crafting. Read from edit events.
TagGameplay tag for effect or sound when this material is hit or removed. Read from edit events; works with GameplayCues and tag-based systems.

Query entries at runtime with Get Material Entry (Index) on the volume actor, or Get Material / Find Material on the set asset. Edit events (On Voxels Removed, On Voxels Added) and the edit result struct include Removed and Added arrays of { Material, Count } — loop those, resolve each index through the set, then grant loot from Yield Id or play FX from Tag.

Edit authorizer

Before the server applies any edit, it calls an object implementing VoxelEditAuthorizer. Implement Authorize Voxel Edit (Volume, Instigator, Brush, Location) and return false to refuse the edit. By default the GameMode is consulted when it implements this interface; override with Set Edit Authorizer on the subsystem to point at any other object (a subsystem, player state, or dedicated rules actor).

The authorizer runs only on the authority. Clients still predict dig and fill locally; if the server rejects the edit, affected chunks roll back to the confirmed state.

Common uses: require a pickaxe id before digging rock (Required Tool Id from the material set), block edits outside a claimed zone, enforce ownership, or scale brush strength from Hardness. A typical tool check: Query Voxel or Line Trace Voxels at the edit location, Get Material Entry on the hit material index, compare Required Tool Id against the equipped tool id on the instigator, return false when it does not match.

Plugin vs game logic

Hardness, tool ids, yield ids and the gameplay tag are metadata for your game. The plugin stores indices, replicates edits and reports per-material counts; your authorizer and event handlers enforce the rules and drive gameplay.

Editing at runtime

Everything goes through the ButterNetVoxelSubsystem (a world subsystem) or the volume actor.

FunctionNotes
ButterNetVoxelSubsystem
Request EditApply a brush at a point. On an authority it applies directly; on a client it predicts dig and fill locally and sends the request to the server.
Request Edit From ViewTrace from the player's view and edit where the voxels are hit. The usual dig/fill input.
Query VoxelSolid or air, material, signed distance.
Line Trace VoxelsFirst solid voxel along a ray, with location, normal and volume.
Find Volumes At / Get VolumesDiscover volumes in the world.
Spawn Volume / Spawn Persistent VolumeCreate volumes at runtime.
Set Edit AuthorizerObject implementing VoxelEditAuthorizer. See Material set & authorizer.
AVoxelVolumeActor
Apply BrushAuthority only.
Get Material EntryName, ids and tag from the definition's material set for a material index. False when none is set.
Export / Import Volume StateSerialise or replace the whole edited state as bytes.
EventsOn Voxels Removed and On Voxels Added include per-material counts. Also On Initial Mesh Complete, On Snapshot Complete, On State Loaded / Saved, On Debris Spawned.

Brush presets (VoxelBrushPreset) describe one tool: shape (sphere or box), mode (Subtract, Add, Paint, Smooth), radius, strength, falloff, material and cooldown. Brushes are quantised to quarter voxels.

Replication

The server applies edits and appends them to a replicated ring of ops; clients apply the same ops in order. Steady-state cost is about 60 bytes per edit.

Clients predict dig and fill immediately; if the server rejects an edit (authorizer, range, rate), the affected chunks roll back to the confirmed state. A client that joins late or falls behind the op history requests chunk snapshots: compressed deltas against the generator baseline, about 1.8 KB per edited chunk, paced by snapshot bandwidth settings. On Snapshot Complete fires when the client is caught up.

Debris pieces are replicated actors with movement replication; the server's physics corrects the clients. Dedicated servers keep full-resolution collision meshes and skip render data.

Persistence

A persistence provider is any object implementing VoxelPersistenceProvider: load bytes for a key, save bytes (with an urgent flag on shutdown), delete a key. The subsystem creates one provider per world from Project Settings → Plugins → ButterNet Voxels → Persistence Provider Class, or you hand it one at runtime with Set Persistence Provider.

The default local file provider writes Saved/<Local Save Directory>/<key>.bnv, one file per key. To turn persistence on, set Persist and a Persistence Key on the definition (or override per actor). The volume loads on BeginPlay (authority only) and saves after the debounce quiet period, on demand, and when the world ends if configured.

You can also use Export Volume State and Import Volume State to move bytes through your own SaveGame or RPC without a provider. The format is versioned and compressed (Oodle); untouched chunks are never stored.

Editor tools

Voxel Sculpt mode sculpts placed blob volumes directly in the level viewport:

  1. Enable preview

    Make sure the volume has Preview In Editor on so its mesh is visible.

  2. Select the mode

    Open the Modes dropdown in the level editor toolbar and pick Voxel Sculpt.

  3. Sculpt

    Hover for the brush outline (red dig, green fill, yellow paint). Drag to sculpt. Hold Shift to swap dig and fill, Ctrl to paint. Each stroke is one undo step and is saved with the level.

Terrain volumes show nothing in the editor and cannot be sculpted there; they are edited in play. See Debug commands for the debug draw modes and the profiling counters.

Project settings

Project Settings → Plugins → ButterNet Voxels

SettingMeaning
Persistence Provider ClassObject that loads and saves volumes. Default: the local file provider.
Local Save DirectoryFolder under Saved used by the local provider.
Save On End PlaySave dirty volumes when the world ends.
Hole Mask Texel CmResolution of the landscape hole mask texture.
Carve Depth Margin CmHow far below the volume's bottom the landscape collision is pushed under dug columns.

Performance tuning

Voxel Size Cm is the biggest lever: halving it costs eight times the voxels. Keep Max Concurrent Mesh Jobs near your worker count and Max Chunk Uploads Per Frame at 2–4 for smooth frames. Turn Cast Shadows off on underground volumes. Use several medium volumes with World Partition instead of one enormous one.

Measured on a desktop CPU: dig ~0.05 ms; one chunk meshed ~0.3 ms on a worker; 1,024 chunks fully meshed in ~320 ms; a breaking cut ~0.3 ms.

Troubleshooting

Ground looks wrong or missing after a reload

The generator (or landscape) changed since the save, so the saved deltas decode against a different baseline. Delete the .bnv file or the key.

Iris requires replicated actors to use registered subobject lists

Add net.SubObjects.DefaultUseSubObjectReplicationList=1 under [SystemSettings].

A static-mesh volume is empty in a packaged build

The mesh needs Allow CPU Access. Cooked builds discard the CPU copy of the vertex data, so the generator has nothing to read — it works in PIE and produces nothing when packaged. See Generators.

A static-mesh volume shows only part of the mesh

The bounds are smaller than the mesh; the log names the chunk range needed.

Client cannot dig

The player must have logged in (the voxel player component is attached at login) and the volume's Replicate must be on.

Nothing happens when editing in the viewport

Select the Voxel Sculpt mode, not Select mode, and make sure the volume is a blob with Preview In Editor on.

Landscape holes look wrong, or work without MF_VoxelHoleMask

Both symptoms come from Terrain Hide Mode. Hide Landscape Components hides whole components and needs no material changes, so holes can look right with no setup. Material Mask needs MF_VoxelHoleMask wired to the landscape material's Opacity Mask — without it you see landscape geometry inside tunnels. See Terrain mode and landscapes.

Debug commands

Everything here is typed into the console (~) at runtime, or passed on the command line with -ExecCmds="…". Nothing needs a rebuild.

Shipping builds have no log

Shipping suppresses logging, so the log-based commands below print nothing there and a failure arrives with no diagnostics at all. When you are diagnosing something, package Development instead — the console and the log both work, and the build is otherwise the same.

Console variables

CommandDefaultEffect
Volumes
bnv.DebugDraw0Draws chunk boxes. 1 chunk state — green dense, cyan generated surface, yellow boundary wall. 2 LOD band — white 0, yellow 1, orange 2, red far. 3 terrain columns — green dug, orange hidden by the host. 0 off.
bnv.LogEdits0Logs every brush application: volume, mode, sequence, instigator, location and the voxels removed and added. Filter the Output Log to LogButterNetVoxels.
Top-Down Mode
bnv.TopDown.Enabled10 disables the mode entirely and restores the hidden chunks. The quickest way to confirm whether Top-Down is responsible for something you are seeing.
bnv.TopDown.Radius-1Overrides the reveal radius, in centimetres. Negative uses the definition's value.
bnv.TopDown.DrawChunks0Outlines every carved chunk this client owns. Green means built from the current scan, red from an older one. A seam on an outline is a chunk-boundary problem; a seam inside one is not.
bnv.TopDown.DrawCarve0Marks every column the scan believes was dug, at its cut height. Compare the footprint against the cave you can actually see.
bnv.TopDown.Debug0Logs the sightline probe, the carve scan and per-chunk re-meshing.

Profiling

stat ButterNetVoxels shows the plugin's own timers. They are the first place to look when frames get uneven rather than uniformly slow.

CounterCovers
Volume TickEverything the volume does per frame on the game thread.
Apply Edit OpOne brush application against the voxel field.
Reconcile PredictionClient-side rollback when the server rejects or reorders a predicted edit.
Apply SnapshotDecoding a chunk snapshot on a catching-up client.
Materialise ChunkTurning a generated or edited chunk into a dense voxel buffer.
Mesh JobA chunk meshing job on the worker pool.
Surface NetsThe surface extraction itself, inside a mesh job.
Build Dynamic MeshBuilding the renderable mesh from extraction output.
Upload Chunk MeshHanding a finished mesh to the component. Game thread — the usual cause of an upload hitch.
Landscape Sample HeightsTerrain volumes sampling the host landscape for their baseline.
Landscape CarveHiding the host surface and lowering its collision under a dug column.

If Upload Chunk Mesh dominates, lower Max Chunk Uploads Per Frame. If Mesh Job dominates, the voxel size is the lever — see Performance tuning.

Log categories

CategoryCarries
LogButterNetVoxelsVolumes, generation, editing, replication, persistence, debris and the landscape host. Warnings here name the volume and, where relevant, the exact chunk range or asset at fault.
LogVoxelTopDownTop-Down Mode probes, scans and chunk builds. Enabled by bnv.TopDown.Debug 1.

Raise verbosity for a session with Log LogButterNetVoxels Verbose, or filter the Output Log by category. Several generator failures are reported only as warnings — a static mesh without Allow CPU Access, or content falling outside the volume bounds — so a volume that looks empty is worth a log check before anything else.

Where to start

SymptomReach for
A volume renders nothingbnv.DebugDraw 1 to see whether chunks exist at all, then the log for a generator warning.
Digging does nothing on a clientbnv.LogEdits 1 on both ends — it shows whether the request reached the server and what it did.
Terrain holes look wrongbnv.DebugDraw 3 to see which columns are dug versus hidden by the host.
Distant chunks look coarse or popbnv.DebugDraw 2 to see the LOD bands and where the transitions land.
A cave roof is not cutting awaybnv.TopDown.DrawCarve 1 for what the scan believes was dug, then bnv.TopDown.DrawChunks 1 for what was rebuilt.
Frame hitches while diggingstat ButterNetVoxels and look at Upload Chunk Mesh against Mesh Job.

Limitations

Landscape grass and foliage are not cleared over holes. The sculpt editor mode works on blob volumes only. Debris uses one convex hull per piece. Static-mesh features thinner than two voxels disappear at that voxel size. Saved state and snapshots assume the generator and its seed are unchanged.

Support

Questions, bug reports and integration help — use the contact form on the main site, or the Fab product Q&A.

← Back to overview