Preface:
Feel free to ignore this blurb, but I wanted to give you perspective and motivation to use this package.
In Crayta, I had to generate a random maze that could be of any size, potentially huge. As an example, I’ll use a 50x50 maze.
Each tile of the maze was represented as a voxel mesh in-game (with dimensions of 20x20x1 voxel cubes). Each voxel cube has a width of 25cm. So one tile was 500x500x25cm big. I cloned a base tile (that I manually made in-engine) for each tile of my maze. So by the end of it (just counting the floor tiles, not the walls), I had 50x50 or 2500 tiles on the floor.
Since I cloned a tile, that was 2500 entities just on the floor. Once I added in walls (up to 4 walls per tile, lets assume an average of 2 walls), I was close to 7,500 entities! Now The game struggles with this many entities. It’s actually better to have one entity (voxel mesh) that is complex, than many many simple voxel meshes. Now at this point, the framerate of my maze was around 9fps with this solution.
Now I wanted to make one voxel mesh that was complex (the entire maze) versus many smaller voxel meshes. However, I quickly ran into a problem. A voxel mesh can only be 6000x6000x6000cm big. My maze was much bigger than this, and would never fit into a single voxel mesh. So optimizing for voxel meshes wasn’t easy.
Introducing: Voxel Management
In an effort to combat having many simple voxel meshes, or one complex, but small and hard to deal with voxel mesh, I made Voxel Management.
The script will allow you to make voxels in any point in space to any other point in space. The script will take care of the rest. It’ll make the least amount of voxel meshes* as possible (* - may not be the absolute least in extreme edge cases).
In addition, it can support many different types of voxel meshes. For example, you can have a mesh that is static, and one that is destructible. This trivializes placements of large amounts of voxels, and is the perfect package for procedurally generated terrain.
Installing & Prep Work
Name of the package: Voxel Management
Simply add the Voxel Management Template to wherever you desire (such as your gameController).
In the property panel, ensure that the “voxelMeshTemplate” property is pointing to the Empty Voxel Mesh template. This is critical as this is what the script is spawning whenever it needs to create new voxel meshes for your request.
Now on the script that will be generating voxels (hereby referred to as SpawningScript), implement the following local variable:
local staticMeshIndex
local destructibleMeshIndex
-- quick reference to the voxel management script
local voxelManagement
These two variables will keep track of which voxel mesh “type” to use when generating voxels. For example, in this case we’re generating one voxel mesh that will be static (cannot be damaged) and one that is destructible (can be damaged/destroyed).
Now, make the following function in your script:
function SpawningScript:OnVoxelMeshCreated(voxelMeshIndex, voxelMesh)
if voxelMeshIndex == destructibleMeshIndex then
voxelMesh.damageEnabled = true
end
end
This is a function that gets called whenever a new voxel mesh is created (again, due to the size limits of a single voxel mesh). Your job is to see if the voxel mesh being created is relevant to you, and if so, make any changes if necessary. In this case, we’re making any destructible voxel meshes have damage enabled.
The last thing we need to do as prep work is register our voxel meshes with the script. To do that, add the following code to your scripts init:
function SpawnScript:Init()
voxelManagement = self:GetEntity().voxelManagementScript
voxelManagement:GetProperties().onVoxelMeshCreated:Listen(self, "OnVoxelMeshCreated")
staticMeshIndex = voxelManagement:CreateNewVoxelMeshType()
destructibleMeshIndex = voxelManagement:CreateNewVoxelMeshType()
end
Using the package
To use the package, simply call the following function:
voxelManagement:PlaceVoxel(voxelAsset <voxelasset>, voxelMeshIndex <number>, position <vector>, size <vector>)
Explaining the properties:
-
voxelAsset - VoxelAsset is the material you want to add. You can expose this as a property on your script, and reference that property (i.e.
self.properties.myVoxelAsset
) - voxelMeshIndex - this is referencing which voxel mesh you want to use for these voxels. Remember that earlier we specified two, one that is static and one that is destructible. Simply pass in which one you want to use
- position - this is the absolute position that you want to add the voxels to in <x,y,z> space
- size - this is the size of the object in terms of width, length, and height. One voxel cube is generally 25 voxels wide, so to make a 2x2x2 voxel cube square, you would pass in a vector of <50,50,50>
Thanks everyone!