Cubiquity for Unity3D 使用 | Cheney Shen

Technology blog

Cubiquity for Unity3D 使用


Cubiquity 相关网站提供了功能健全的体素解决方案,特别是功能还切分了核心的引擎以及各个平台的插件,详细的使用说明和问答,非常适合快速实现体素内容。这里介绍一下这一款工具的基本内容和框架,以及使用上的一些总结。


  • Installation

There are currently three ways of obtaining Cubiquity for Unity3D.

Enabling ‘unsafe’ code


Cubiquity for Unity3D is built on top of a native code (C++) library which handles most of the heavy-lifting behind the scenes.These meshes need to be passed from the unmanaged native-code world of Cubiquity into the managed-code world of C# and Unity.

The C# language provides (at least) two ways to perform this communication.

The first is is via Marshalling.

The second approach is to make use of the ‘unsafe’ keyword to enable pointers and direct memory access in our C# code, so that we can directly read from the memory owned by the native code library.

The second approach is faster, cleaner, and is what we recommend.


If you do not already have .rsp files in your Assets folder then the easiest approach is to copy the sample files which we provide in the Assets/Cubiquity/Unsafe folder (only copy the .rsp files – corresponding .meta files will be generated automatically).

If you do already have conflicting .rsp files then you will need to manually add the required compiler switches to them. These switches are:

-unsafe -define:CUBIQUITY_USE_UNSAFE

The first of these enables unsafe code for the compiler, and the second tells Cubiquity for Unity3D that this mode is available so that it can use the correct code path.


  • Quick Start

  • Creating your first voxel terrain

Cubiquity for Unity3D supports two types of voxel environments.



Begin by opening the scene ‘EmptySceneWithLighting’ in the Assets/Cubiquity/Examples folder.

Now create a Terrain Volume from within the Unity3D editor by going to the main menu and selecting GameObject -> Create Other -> Terrain Volume.



Your new terrain should be automatically selected, and as with any other Unity object you can scale, rotate, and translate it by using the the usual gizmos.

To actually edit the terrain you need to select one of the tools from the ‘Terrain Volume (Script)’ component in the inspector.


Take some time to experiment with the editing tools which are available. You can choose a tool to apply (sculpt, smooth, etc) by selecting one of the buttons at the top of the inspector, and then choose your desired brush options and/or materials. Left-clicking on the terrain will then apply the tool.


Now lets try adding a collider so that other objects can interact with the terrain.

To do this we add a ‘Terrain Volume Collider’ component through Add Component -> Scripts -> Cubiquity -> Terrain Volume Collider.

Note that this is different from the ‘MeshCollider’ which is often added to other Unity objects.

To test the collisions we can now import one of the standard Unity character controllers and walk around the terrain in play mode.

Be aware that it can take a few seconds for the terrain to generate after you press the play button, so for this reason you should set your character to start a hundred units or so above the terrain. This way the terrain will have time to load before the character reaches ground level (there are better approaches, but this is fine for quick-start purposes).(游戏开始需要时间生成地形,因此要把对象放得高点避免还没生成地形人就掉下去了)


  • Creating your first colored cubes volume


Cubiquity for Unity3D also supports a second type of voxel environment in which the world is built out of millions of colored cubes.


You can then create a Colored Cubes Volume by going to the main menu and selecting GameObject -> Create Other -> Colored Cubes Volume. The initial volume should look like that shown below:



the editing facilities of this are currently very limited, and only allow you to create single cubes at a time by left-clicking on the volume.

Let’s try replacing the volume data with one of the example volumes which comes with Cubiquity. (使用一进编辑好的数据)

To do this, select the colored cubes volume, go to ‘Settings’ in the inspector, and click the small circle next to the ‘Volume Data’ field.

From here you can select the ‘VoxeliensColoredCubes’ asset which will cause it be be used as the source data for the volume (this is a map from our previous game Voxeliens).


The asset you have selected is actually just a very thin wrapper around our Cubiquity voxel database file format. If you click on the ‘Volume Data’ field (rather than clicking on the circle, as you did previously) then Unity will show you that the asset actually exists in ‘Assets/Cubiquity/Examples/Basic’.

Modifying the volume at run-time

We will now give a quick demonstration of how the volume can be modified during gameplay.

Go to the ‘Assets/Cubiquity/Examples/SharedAssets/Scripts’ folder and find the ‘ClickToDestroy’ script.

Drag this on to the Colored Cubes Volume in the scene hierarchy to add it as a component.

We will also want a collider for this to work correctly so add one via Add Component -> Scripts -> Cubiquity -> Colored Cubes Volume Collider

(note that a Colored Cubes Volume Collider is different to the Terrain Volume Collider you used in the earlier example)

When you press play you should find you are able to fly around the scene, and that if you left-click on the volume it will create a small explosion which breaks off the cubes in the surrounding area. The separated cubes then fall under gravity and can bounce around the scene. This is simply an example of the kind of functionality we can achieve, and you can learn more by reading the Class List later in this user manual, or by looking at the code in ClickToDestroy.cs.



  • Main Principles

  • Voxel Engine Concepts

Cubiquity is a voxel engine, which means that it represents it’s objects as samples on a 3D grid.

In many ways a voxel can be considered the 3D equivalent of a pixel.

Rendering such a 3D grid directly is not trivial on modern graphics cards as they are designed for rendering triangles rather than voxels.


  • ‘Cubiquity’ vs. ‘Cubiquity for Unity3D’

‘Cubiquity’, is a native code (i.e. C/C++) library for storing, editing, and rendering voxel worlds.

‘Cubiquity for Unity3D’ is a set of C# scripts which connect Cubiquity to the Unity3D game engine. These scripts allow Unity3D games to create, edit and display Cubiquity volumes.

Calling the Cubiquity Native-Code Library (P/Invoke技术)

Functions defined in the native-code library can be called from Unity3D scripts using some magic known as P/Invoke. The file ‘CubiquityDLL.cs’ uses this P/Invoke technology to provide thin .NET wrappers around each function which is available in the Cubiquity engine.

in particular that it cannot be used with the Unity3D web-player because this does not support native code.

The Cubiquity Voxel Database Format (SQLite数据库)

The Cubiquity voxel engine stores a volume as a Voxel Database, which is a single file containing all the voxels in the volume.

Internally it is actually an SQLite database and so can be opened with a tool such as SQLite Browser.


  • Key Components

we have adopted a compoent-based model in which the user can add a GameObject to a scene, give it a ‘Volume’ component to make it into a voxel object, and then add VolumeRenderer and VolumeCollider components to control it’s behaviour.

With this in mind, the structure of a typical volume is as follows:


The structure of a typical volume


The Volume Component


Adding a Volume component to a GameObject makes it into a voxel object.

Volume components also have custom inspector implemented which allow you to edit the volume in an intuitive way.

Cubiquity for Unity3D wraps voxel databases with a class called VolumeData, and more specifically with its subclasses called TerrainVolumeData and ColoredCubesVolumeData.


The VolumeRenderer Component


The visual appearance of the volume is controlled by the VolumeRenderer, and if a VolumeRenderer is not present then the volume will not be visible in the scene.


The VolumeCollider Component


The VolumeCollider component should be attached to a volume if you wish a collision mesh to be generated.

This will allow other object in the scene (such as rigid bodies) to collide with the volume.



  • Obtaining Volume Data


  • Importing From External Sources

where did these .vdb files come from?

Note that both Magica Voxel and image slices are only appropriate for importing colored cubes volumes.

Currently there are no methods for creating terrain volumes outside of Cubiquity for Unity3D, but you can still create them procedurally as discussed later.


Importing From Magica Voxel

You may wish to model your voxel geometry in an external application such as Magica Voxel, Voxel Shop, or Qubicle Constructor.

Such applications will typically allow more comprehensive editing options than we will ever provide in Cubiquity, and Cubiquity already provides the option to import Magica Voxel files (others will follow in the future).

This is done by the use of the command-line ProcessVDB tool.

To use this tool you should open a command prompt and change to the StreamingAssets\Cubiquity\SDK directory. From here you can run:

ProcessVDB.exe -import -magicavoxel input.vox -coloredcubes output.vdb

You can then copy the resulting .vdb into the StreamingAssets\Cubiquity\VoxelDatabases folder before following the instruction in Creating From An Existing Voxel Database to import it into Unity.


Importing From Voxlap

ProcessVDB.exe -import -vxl input.vxl -coloredcubes output.vdb


Importing From Image Slices(图片切片)

The same tool can be used to import colored cubes volume from a series of color images representing slices through the volume

(see Assets\Cubiquity\Examples\VolumeData\VoxeliensLevel3 for an example of such a series of slices).

You can call the converter in the same way as before, but providing a path to a folder containing image slices rather than to a Magica Voxel .vox file:

ProcessVDB.exe -import -imageslices /path/to/image/folder -coloredcubes output.vdb



  • Generating Volume Data Through Scripts

Cubiquity for Unity3D provides a very simple but powerful API for generating volumes through code.

Each volume is essentially just a 3D grid of voxel values, and the API gives you direct access to these through the VolumeData’s GetVoxel(…) and SetVoxel(…) methods.


Using a noise function: Evaluating a 3D noise function (such as Perlin noise or Simplex noise) at each point on the grid can generate both natural and surreal environments. Multiple octaves of noise can be combined to add additional detail. Please see the ‘Procedural Generation’ example in the examples folder.


Reading an input image: The ‘Maze’ example (see the examples folder) reads a 2D image of a maze and sets the height of voxel columns based of whether the corresponding pixel is black or white. The same principle can be applied to generating a terrain from a heightmap.


Building planets from spheres: You can create spheres by computing the distance function from a point, and a cube map can then be used to apply a texture. The ‘Solar System’ example shows how this can be used to create planets.



  • Duplicating, instancing, and sharing of volume data

  • General considerations

Cubiquity for Unity3D provides full support for having multiple volumes in a scene.

However, these are two main things to keep in mind and which we shall state here at the beginning.

  1. In many cases you will be better off having a single volume in your scene.
  2. Avoid having multiple VolumeData instance referencing the same voxel database.

so we strongly suggest that you avoid duplicating volume instances.

  • Scenarios

We now look at a few possible scenarios which exemplify the way in which multiple volumes should or should not be used.


Modeling a large terrain

It may seem tempting to break a large terrain down into smaller volumes in order to benefit from optimizations such as occlusion culling. However, Cubiquity already implements such optimizations internally and attempting to use multipl volumes in this scenario will likely lead to a loss or performance.


Modeling a city

If you have a city with a number of identical buildings then it might seem desirable to represent the building as a read-only volume and then place multiple instances of it. However, it is much better to have a single volume representing your whole world, and to write the voxel data for the buildings directly into this single main volume in multiple locations.

As will as giving better performance, this will make it easier to update the volume in response to events such as explosions. With multiple volumes you would need to iterate over then to determine which one are affected by the explosion, but with a single volume this becomes trivial.

The downside of this is that it may be harder to build such a volume, as you need a world-creation process which can build much larger environments.


Modeling planets/asteroids

This is a scenario where we believe the use of multiple volumes is appropriate, and an example is included with Cubiquity for Unity3D (the ‘Solar System’ example). In this case we provide a single voxel database which is referenced by two VolumeData assets, both of which have their read-only flags set. These two VolumeData assets are used by two seperate volumes representing the Earth and the Moon.

The voxel data is actually a series of concentric spheres with different material identifiers, representing the layers which are present in a typical planet. The actual material and set of textures we apply can differ between the volumes, giving the Earch and moon different visual appearances. In play mode it is possible to independantly modify each of the bodies as the changes are stored in a temporary location, but as mentioned previously these changes cannot be written back to the voxel database because it is opened as read-only.

This scenario is appropriate for multiple volumes primarily because we want to have different transforms applied to each (i.e. the Moon orbits the Earth while the Earth orbits the Sun).








Volume.cs:两种Volume风格的父亲,Base class representing behaviour common to all volumes.

包括基本的数据存储单元mData (VolumeData定义的结构)

VolumeData::ScriptableObject(unity提供的非Game Objects对象派生类接口):Base class representing the actual 3D grid of voxel values。描述的是创建,连接和操作Voxel数据库的方法。











data.SetVoxel(x, y, z, materialSet);

materialSet:0-255 0表示不存在,源程序值越大就是硬度越高,就会用岩石的纹理,低的话就是草地的纹理。












volumeRenderer.material.SetTextureScale(“_Tex0”, new Vector2(0.062f, 0.062f));





Post a Comment

Your email address will not be published. Required fields are marked *

  • Categories

  • Tags