I’ve continued evolving the voxel engine. I was a bit brief previously so I figured I’d expand on it here.
This was a straight forward implementation. I had one GameObject that I considered the WorldController. It created the camera and player as well as the 3d array which contained the Voxels (also GameObjects). I had started with a world of length 100x100x100 and was table to create the floor of 100x100 without any problems. Changing it to 200 (so a 200x200 voxel ground) would make the app OOM. I didn’t bother finding a middle ground or trying to optimize it because I knew this was just a quick implementation.
All of the voxels started off disabled so that Unity wouldn’t render them. Then the world figured out the closest 10x10x10 voxels around the player and would set those as active so that they’d render. On every frame, I’d deactivate the GameObject voxels then figure out the next set of voxels to render and activate them.
Simple WASD controls were added to move the player around to ensure that the voxels properly de-rendered and rendered as needed.
As an added bonus, hovering over a voxel would, over time, darken the voxel. Moving away and coming back would keep that color.
First and foremost, I didn’t want a lot of GameObjects hanging around if they weren’t actually being rendered. They were just storage for voxel data, so why not decouple the data from the render-able object? I create a VoxelInfo class and moved everything relating to the data of the voxel (location, voxel type, etc) into that. I created the 3d array out of VoxelInfos instead of GameObject voxels. In addition to this, I moved all 3d array-related methods and variables into a new class that manages that 3d array. This now lives in the WorldController. Inside of the world controller we still have the player so for each frame we:
- Clear what we consider the closest voxels (as voxel infos) and any GameObject voxels we might have created last frame
- Ask the world to give us the VoxelInfos closest to the player’s location
- Ask the infos what type of voxel they are (only one for now - red)
- For each VoxelInfo, create a GameObject voxel
Using this new lighter-weight object (VoxelInfo), I was able to scale up the world to 500x500x500 and create a ground of 500x500 VoxelInfos.
Each time I create a voxel GameObject, I “SendMessage” (ugh) to it with the specific VoxelInfo it will be representing on screen. Using this GameObject, I implemented a voxel health system (currently 1 hp per voxel). And what good is health if you can’t decrement it? The player has two modes now - destroy and build. You can press 1 to go into build mode and 2 to go into destroy mode. Clicking on a voxel will build a voxel on top of the voxel you clicked (current limitation, will change). Clicking on a block in destroy mode will permanently delete it.
With building comes the need to go up, so we’ve got some jumping action with the space bar. Jumping is limited to when the player in on a ground (voxel), achieved by using a short ray cast down from the bottom of the player.
On the suggestion of a friend, the player is now faster so you feel like you’re hauling ass through the world.
If you have any question about any of this, come to my stream on Twitch.tv or leave a comment below.
WASD - move
1, 2 - change between building and destroying mode
spacebar - jump
You can only build on top of other voxels for now.