MicroVoxels API

advanced scripting

Voxel Play 3 · Scripting / API

Class: Members on this page belong to VoxelPlayEnvironment (access via VoxelPlayEnvironment.instance) and to the MicroVoxels class. Read MicroVoxels & Slabs first for the underlying concepts.

Each regular voxel can be subdivided into a 16x16x16 grid of microvoxels. The runtime API on this page lets you place, destroy and query microvoxels at any world position, control which slab layout a voxel uses, attach a secondary voxel type for two-material rendering, and feed custom occupancy patterns into the regular VoxelPlace pipeline. The same calls power both the slab system (top/bottom halves) and arbitrary user-authored shapes.

Most methods accept a world Vector3d position that is snapped to the parent voxel grid. Some methods come in a VoxelChunk chunk, int voxelIndex overload to avoid the position-to-chunk lookup when the chunk is already known.

Placing MicroVoxels

bool MicroVoxelPlace(Vector3d position, VoxelDefinition voxelType, Color tintColor = default, int rotation = 0)

Places a single microvoxel at the given world position. If the parent voxel does not yet contain microvoxels, it is converted on the fly. Returns true if the microvoxel was added.

position
World position. The microvoxel cell is derived from the fractional part (16 cells per axis inside the parent voxel).
voxelType
Voxel definition that supplies the texture/color for the new microvoxel.
tintColor
Optional tint applied to the microvoxel.
rotation
Texture rotation index (0-3).
bool MicroVoxelPlace(ref VoxelHitInfo hitInfo, int size, VoxelDefinition voxelType, float probability = 1f, Color tintColor = default, int rotation = 0)

Brush variant: places a cubic block of microvoxels of edge size around the impact point described by hitInfo. Typical use is from a RayHit result to "paint" microvoxels on a surface.

hitInfo
Hit info returned by RayHit (contains chunk, voxel index and exact impact position).
size
Brush size in microvoxel cells (1-16). 1 places a single microvoxel.
probability
Per-cell probability of being filled. Use values below 1 for a noisy / dithered brush.
bool MicroVoxelPlaceSlab(Vector3d position, VoxelDefinition voxelType, Color tintColor = default, int rotation = 0, bool topHalf = false, bool replace = false, bool refresh = true)

Places a half-voxel slab. The parent voxel is converted to MicroVoxelLayout.Slabs and either the top or bottom half is filled, depending on topHalf.

topHalf
true places the top slab; false the bottom slab.
replace
If true, replaces an existing slab in the same half. If false and that half is already filled, the call is a no-op.
refresh
Immediately rebuilds the chunk mesh. Disable when placing many slabs in a batch, then call ChunkRedrawAll().

Destroying MicroVoxels

bool MicroVoxelDestroy(Vector3d position)

Removes the microvoxel cell at the given world position. Returns true if a microvoxel was present and was cleared. When the last microvoxel of a parent voxel is removed, the parent voxel itself is cleared.

bool MicroVoxelDestroy(ref VoxelHitInfo hitInfo, int size, float probability = 1f)

Brush variant: clears a cubic block of microvoxels of edge size around the impact point. Use it for hit-based digging or weapon impacts.

size
Brush size in microvoxel cells (1-16).
probability
Per-cell removal probability. Below 1 produces a chipped / eroded look.
bool MicroVoxelDestroySlab(Vector3d position, bool topHalf)

Removes one of the two halves of a slab voxel. Returns true if the half existed and was cleared. If both halves end up empty, the parent voxel is removed.

Querying MicroVoxels

bool IsMicroVoxelAtPosition(Vector3d position)

Returns true if the parent voxel at the given position holds microvoxels (slab or custom shape).

bool IsMicroVoxelAtPosition(Vector3d position, out MicroVoxels mv)

Same as above but also returns the MicroVoxels instance attached to the parent voxel.

bool IsMicroVoxelAtPosition(VoxelChunk chunk, int voxelIndex)

Chunk-index overload, skips the world-to-chunk lookup.

bool IsMicroVoxelAtPosition(VoxelChunk chunk, int voxelIndex, out MicroVoxels mv)

Chunk-index overload with MicroVoxels output.

bool IsMicroVoxelAtPosition(ref VoxelHitInfo hitInfo)

Returns true if the impact described by hitInfo lies on a voxel that contains microvoxels.

MicroVoxels GetMicroVoxels(Vector3d position)

Returns the MicroVoxels attached to the parent voxel at position, or null if the voxel has none.

MicroVoxels GetMicroVoxels(VoxelChunk chunk, int voxelIndex)

Chunk-index overload.

Boundsd GetMicroVoxelBounds(ref VoxelHitInfo hitInfo, int microVoxelSize, float padding = 0)

Computes the world-space bounds of a microvoxel brush of microVoxelSize cells centered on the impact point. Useful for highlight overlays.

bool IsBottomHalfAtPosition(Vector3d position)

Returns true when the parent voxel at that position is a slab with only the bottom half filled.

bool IsBottomHalfAtPosition(VoxelChunk chunk, int voxelIndex)

Chunk-index overload.

bool IsTopHalfAtPosition(Vector3d position)

Returns true when the parent voxel is a slab with only the top half filled.

bool IsTopHalfAtPosition(VoxelChunk chunk, int voxelIndex)

Chunk-index overload.

bool IsHalfVoxelAtPosition(Vector3d position)

Returns true when the parent voxel is a slab, regardless of which half is filled.

bool IsHalfVoxelAtPosition(VoxelChunk chunk, int voxelIndex)

Chunk-index overload.

Layout & Secondary Type

Each voxel that holds microvoxels has a MicroVoxelLayout mode. Default stores arbitrary occupancy; Slabs packs two half-voxels (top + bottom) into a single voxel and can render each half with a different texture using the secondary type.

void MicroVoxelSetLayout(Vector3d position, MicroVoxelLayout layout)

Switches the layout mode of the voxel at the given position. Switching from Default to Slabs reinterprets the existing occupancy as two halves.

void MicroVoxelSetLayout(VoxelChunk chunk, int voxelIndex, MicroVoxelLayout layout)

Chunk-index overload.

MicroVoxelLayout MicroVoxelGetLayout(Vector3d position)

Returns the current layout of the voxel at position.

MicroVoxelLayout MicroVoxelGetLayout(VoxelChunk chunk, int voxelIndex)

Chunk-index overload.

void MicroVoxelSetSecondaryType(Vector3d position, VoxelDefinition secondary)

Attaches a secondary VoxelDefinition to the voxel. In Slabs layout it provides the texture for the upper half (while the primary type textures the lower half).

void MicroVoxelSetSecondaryType(VoxelChunk chunk, int voxelIndex, VoxelDefinition secondary)

Chunk-index overload.

void MicroVoxelClearSecondaryType(Vector3d position)

Removes any secondary type attached to the voxel.

void MicroVoxelClearSecondaryType(VoxelChunk chunk, int voxelIndex)

Chunk-index overload.

Placing whole voxels with custom MicroVoxels

The regular VoxelPlace overloads accept an optional microVoxels argument. When provided, the placed voxel is initialized with that occupancy pattern instead of a full cube. This is how you spawn pre-authored shapes (stairs, slabs, decorations) in a single call.

bool VoxelPlace(Vector3d position, VoxelDefinition voxelType, bool playSound = false, Color tintColor = default, float amount = 1f, int rotation = 0, bool refresh = true, bool placeMicroVoxels = true, MicroVoxels microVoxels = null, bool slabMode = false)

Places a voxel and optionally seeds it with a custom MicroVoxels pattern.

placeMicroVoxels
When true the voxel may host microvoxels. Set to false to force a regular full-cube voxel even if the definition supports microvoxels.
microVoxels
Optional pre-built MicroVoxels pattern. When provided, the voxel is initialized with this occupancy.
slabMode
When true, the voxel is created in MicroVoxelLayout.Slabs.
bool VoxelPlace(List<VoxelIndex> indices, VoxelDefinition voxelType, Color tintColor = default, bool refresh = true, bool placeMicroVoxels = true, MicroVoxels microVoxels = null, bool slabMode = false)

Batch overload: places voxels at every VoxelIndex in the list, optionally sharing the same MicroVoxels pattern across all of them.

The MicroVoxels class

MicroVoxels stores the per-cell occupancy of a single voxel (16 cells per axis = 4096 cells total) as a bit-packed array. Build instances in advance for reusable shapes, then pass them to MicroVoxelPlace or VoxelPlace.

Bulk operations

void Fill()

Marks every cell as occupied. The result is equivalent to a solid voxel.

void Clear()

Marks every cell as empty.

MicroVoxels Clone()

Returns a deep copy of the instance, with its own grid buffer. Use it before mutating a shared template.

void CopyFrom(MicroVoxels mv)

Replaces the current occupancy with the contents of mv.

Per-cell operations

bool SetOccupied(int x, int y, int z)

Marks the cell at coordinates (x, y, z) as occupied. Returns true if the cell changed state. Coordinates are in the range [0, COUNT_PER_AXIS).

bool SetOccupied(int microVoxelIndex)

Linear-index variant. microVoxelIndex = x + y * 16 + z * 256.

bool SetUnoccupied(int x, int y, int z)

Clears the cell at (x, y, z). Returns true if the cell changed state.

bool SetUnoccupied(int microVoxelIndex)

Linear-index variant.

bool IsOccupied(int x, int y, int z)

Returns true when the cell at (x, y, z) is occupied.

bool IsOccupied(int microVoxelIndex)

Linear-index variant.

Static templates

The class exposes a few ready-to-use shapes. They are cloned internally on placement, so it is safe to reuse the same template across calls.

static MicroVoxels halfSurfaceVoxelTemplate

A thin horizontal layer that fills only the bottom row of cells. Used for surface decals (snow dusting, paint, water film).

static MicroVoxels topHalfVoxelTemplate

Fills the upper half of the voxel. Equivalent to placing a top slab.

static MicroVoxels bottomHalfDefaultVoxelTemplate

Fills the lower half of the voxel. Equivalent to placing a bottom slab.

Constants

const int COUNT_PER_AXIS = 16

Number of microvoxel cells along each axis of a parent voxel.

const int COUNT_PER_VOXEL = 4096

Total number of microvoxel cells per parent voxel (163).

const float SIZE = 1f / 16

World-space size of a single microvoxel cell, in voxel units.

CreateMicroVoxels helper

Helper methods on VoxelPlayEnvironment that fill a MicroVoxels instance from common inputs. The mv argument is passed by ref so it can be allocated on demand by the helper.

bool CreateMicroVoxels(bool[,,] occupancy, ref MicroVoxels mv, bool shared = true)

Builds a MicroVoxels from a 3D boolean occupancy array of size [16, 16, 16]. Each true entry maps to an occupied cell.

shared
When true (default), if an identical shape already exists in the internal cache it is reused. Disable to always allocate a private instance.
bool CreateMicroVoxels(int bottomY, int topY, ref MicroVoxels mv, bool shared = true)

Slab builder: fills every cell whose Y coordinate falls in the inclusive range [bottomY, topY]. Use (0, 7) for a bottom slab and (8, 15) for a top slab.

Integration with RayHit

All RayHit overloads accept two microvoxel-specific parameters that let a single call carve a microvoxel-aware impact.

bool RayHit(Rayd ray, int damage, out VoxelHitInfo hitInfo, float maxDistance = 0, int damageRadius = 1, bool addParticles = true, bool playSound = true, int microVoxels = 0, float microVoxelDestroyProb = 1f, IgnoreWaterOption ignoreWater = IgnoreWaterOption.DefinedByWaterVoxelDefinition, bool restrictToSlab = false)

When microVoxels > 0 and the impacted voxel hosts microvoxels, RayHit removes a brush of microVoxels microvoxel cells around the impact point instead of damaging the whole voxel.

microVoxels
Brush size in microvoxel cells (0 disables the microvoxel-aware path).
microVoxelDestroyProb
Per-cell removal probability, mirrors MicroVoxelDestroy.
restrictToSlab
If true, only slab halves can be affected by the hit.

Code examples

Place a 3x3x3 cluster of microvoxels

using VoxelPlay;
using UnityEngine;

public class MicroCluster : MonoBehaviour
{
    public VoxelDefinition gold;

    void Start()
    {
        var env = VoxelPlayEnvironment.instance;
        Vector3d center = new Vector3d(0, 32, 0);

        // Place a 3x3x3 cluster of microvoxels around 'center'
        for (int x = -1; x <= 1; x++)
        {
            for (int y = -1; y <= 1; y++)
            {
                for (int z = -1; z <= 1; z++)
                {
                    Vector3d p = center + new Vector3d(
                        x * MicroVoxels.SIZE,
                        y * MicroVoxels.SIZE,
                        z * MicroVoxels.SIZE
                    );
                    env.MicroVoxelPlace(p, gold);
                }
            }
        }
    }
}

Build a custom slab voxel from an occupancy array

using VoxelPlay;
using UnityEngine;

public class CustomShape : MonoBehaviour
{
    public VoxelDefinition stone;

    void Start()
    {
        var env = VoxelPlayEnvironment.instance;

        // Build a pyramid that occupies the bottom half of a voxel
        bool[,,] occ = new bool[16, 16, 16];
        for (int y = 0; y < 8; y++)
        {
            int margin = y;
            for (int x = margin; x < 16 - margin; x++)
            {
                for (int z = margin; z < 16 - margin; z++)
                {
                    occ[x, y, z] = true;
                }
            }
        }

        MicroVoxels shape = null;
        env.CreateMicroVoxels(occ, ref shape);

        env.VoxelPlace(
            new Vector3d(4, 32, 4),
            stone,
            placeMicroVoxels: true,
            microVoxels: shape
        );
    }
}

Query a hit and destroy a microvoxel brush

using VoxelPlay;
using UnityEngine;

public class MicroPick : MonoBehaviour
{
    public Camera cam;

    void Update()
    {
        if (!Input.GetMouseButtonDown(0)) return;

        var env = VoxelPlayEnvironment.instance;
        Rayd ray = new Rayd(cam.transform.position, cam.transform.forward);

        if (env.RayHit(ray, damage: 0, out VoxelHitInfo hit, maxDistance: 50))
        {
            if (env.IsMicroVoxelAtPosition(ref hit, out MicroVoxels mv))
            {
                // Surgical 3-cell brush on the impact point
                env.MicroVoxelDestroy(ref hit, size: 3, probability: 1f);
            }
            else
            {
                // Convert the whole voxel into a bottom slab
                env.MicroVoxelPlaceSlab(hit.voxelCenter, hit.voxel.type, topHalf: false);
            }
        }
    }
}
Was this page helpful?