In-Game Editing Tools

benboesel posted this 23 June 2015

Hello! First off, thanks for the the amazing asset! A few quick questions.

First, how would you suggest implementing the click and drag "Draw box to add voxels" while in-game? Is there a function from the editor script I can modify to accomplish this easily? I know how to add/delete blocks inside a sphere (like the explode function), but click and dragging a box in real time is a tad confusing to me.

When adding one block at a time in-game, I'm using a simple raycast method, backing up one voxel, then adding my block. I want to be able to hold down my mouse button and add voxels to the surface of my voxelworld. Right now if I hold down the mouse, it will add blocks but it will also start to add blocks ontop of that block. If I want to simple cover the surface with one block in depth, should I add blocks but keep them inactive somehow until I release the mouse?

My last question is similar. I want to be able to, in-game, place prefab voxels onto my main voxel world (exactly like the "brush" . Right now I raycast to find the point the cursor is hitting, back up a space, and then add my prefab picavoxel. That being said, it remains its own gameobject/volume, not integrated into the main Voxel Volume. I'm assuming I could loop through all the world positions, check for a voxel in the main Volume, then add blocks there? Is there a more elegant solution for prefab/brushing items onto other volumes in-game

Thanks so much!

Order By: Standard | Newest | Votes
GarethIW posted this 24 June 2015

So the way I do this in the editor is by having a second array of voxels that represent the current state of editing. That's the EditingVoxels field in Frame.cs.

For the box-drawing example, this array is initialised when the click begins, and the current Voxels array is copied over to it. From that point on, while the mouse button is held down, all changes are made on the EditingVoxels array.

When the mouse button is released, the changes are copied back from the EditingVoxels array to the Voxels array.

This also eliminates the issue you have with holding down the mouse button with single-voxel editing; because you're ray-casting against the Voxels array (how the volume looked before you started editing), but making changes to the EditingVoxels array (how the volume looks now).

The EditingVoxels array is always on the Frame class (it's not edit-time-only), so you could use it yourself in-game if you wanted. The code is already there in UpdateChunks that will generate the mesh from EditingVoxels instead of Voxels if the EditingVoxels array is not null and actually contains data.

For brush drawing, you're on the right path. You could use a prefab volume to represent the brush and position that prefab at the raycast point (perhaps add transparency or something so that it is ghosted). But when you actually click to paint, you need to iterate over your prefab's voxel array and copy the voxels across to the target Volume (either by using SetVoxelAtArrayPosition, or just setting the voxels in the array directly).

This would probably be a better way of doing it than the way I do it in the editor, where I again use the EditingVoxels array to draw and clear the brush voxels whenever the mouse is moved, and then copy the brush voxels over to the Voxels array when the click occurs.

Hope that helps explain how I do things in-editor. Again, I'm sorry I'm not providing copy-and-paste code for you to use, but editing is a HUGE topic that is difficult to implement (as I'm sure you are now realising!) and would be different for every game that needed to implement it.

Tommy posted this 01 July 2015

Hey, I am working on in-game editing tools as well! I only just started so my current implementation is rather simple and far from perfect but I would like to share with others. I currently can add/subtract/paint single voxels. GarethIW explained it really well and this post helped me a lot!

I first cast a ray using Unity's Physics.Raycast and retrieve the volume component from the object that was hit. To get the PicaVoxelPoint I use volume.GetVoxelArrayPosition( hit.point ) which returns the x/y/z position of the voxel inside the chunk. To get the index inside the voxel array you can use the x/y/z values like x+volume.xsize(y+volume.ysizez).

Next I allocate the frame.EditingVoxels as a new voxel array with the dimensions of the volume and copy the original voxels using frame.Voxels.CopyTo( frame.EditingVoxels, 0 )

To subtract a single voxel in the volume I check if frame.EditingVoxels[index] is active and change the properties of that voxel by simply overwriting it with a new voxel that has active set to false.

To finalize the editing the edited voxels are copied back into the original voxel array using frame.EditingVoxels.CopyTo( frame.Voxels, 0 ), call volume.UpdateAllChunks() and set the editingvoxels back to null.

Most problems I encountered are from trying to raycast because it is returning a point on the hitbox of the volume or it is returning the parent object. I suggest to look inside VolumeEditor.cs to see how it is done for PicaVoxel!

Kind regards, -Tom

Our 127 members have posted 466 times in 112 discussions