Voxel Destruction, help me optimise network usage

I’m trying to make a voxel destruction system which will have lower network usage.

Context:
I have a voxel destruction system which runs on the server side.
The destruction works by detecting where/when a hit occurs and then system gets any parts within the area of the hit (based on a radius) (it destroys any parts in the radius that are smaller than the voxelSize). The system then either split the part into smaller parts (to make it less intensive) and or create an array of voxel positions of size ‘voxelSize’ in a parallel thread, which is populated based on the size of the part.
The system then checks for voxels within a radius and removes them from the array, it then goes through a greedy meshing algorithm, and then resyncs the thread and creates all the voxels. After all the voxels are made a weld system goes through every voxel welds all touching parts (voxels or not).
(I missed out some stuff, but it’s not important)

Videos for reference:

This works well, until you look at the network usage.
Originally I thought this was due to the particles being spawned (since I was doing it in a stupid way), but that was not the case.

I decided to try move everything to the client, which completely reduced all the network load (as expected).

I’m pretty sure all or most of the network load is due to the mass amount of parts being instantiated.

My main problem is that this no longer syncs with the server and/or other clients. It roughly syncs with other clients (due to them enacting the same logic), however, when removing voxels within the radius from the voxel array, there is a randomness factor (so that it doesn’t carve out a perfect sphere), this would cause discrepancies between the clients (I suppose I could send a seed for randomness for each voxel destruction). Another problem is that new players will be unable to see the destroyed terrain when loading in, and any npc pathfinding on the server will be unable to react to the changes.

My main question is whether anybody can think of an effective way to either sync the destruction with the server, or to keep the calculations on the server, but think of some way to reduce the network load? or something?

If you have any questions on how the system works, please ask. Or if you have any suggestions to optimise it.

sorry for yapfest.

Note - I may take a while to respond to this thread, sorry.

2 Likes

Here’s what I would do:


For players joining the game:

Server detects a new player and sends the entire blocks list back to the clients to get an initial view of what the blocks look like currently.


For players playing the game:

Run the “good looking” destruction (piece by piece) on the client and then only update the server after the entire destruction (finished hole) occurs. You would then only send the destroyed blocks to the server so it can remove some of them using the randomness you were talking about. Then it would send the blocks it destroyed back to the client.


This should theoretically decrease the amount of data needing to be sent from client to server and should update between players. I’m not exactly sure how your voxel technique works though so I’m not sure if this is completely possible.

1 Like

Thanks for the reply.
I cobbled together a system roughly based on your suggestions.
Basically, I’ve set it up so a remote function calls to every client to try initiate the destruction, the server then waits until every client has successfully destroyed the voxels (or waits until a set timeout has been reached) and then does the destruction on the server (because of how the destruction works it’s far faster to redo the calculations rather than try send the destroyed parts, and do something with them, randomness can simply be set by sending a seed to the clients), parenting the new voxels to the camera (If you parent stuff to the camera it doesn’t replicate to the client). So far this seems to sync up well. I haven’t spent very long making or testing it, so I don’t know how reliable it is. The network usage is unaffected by the destruction now (compared to it massively increasing the client receiving before).

I plan to copy all the parts in the camera to new clients that are joining (this will be the next thing I do) so that they don’t need to recompute all the destruction/so they can actually see the destruction. I’ll also need to experiment with how the physics sync (it’s probably fine), and figure out what to do if a client takes too long or fails to compute the destruction.

I’ll continue to update this thread with my progress until I get a satisfactory result.

1 Like

I recommend try Blink | An IDL compiler written in Luau for ROBLOX buffer networking. | 0.18.5 I used it on my voxel system it pretty good almost no network usage but it really hard to write in interpeter tho

1 Like

Yo just checking in! Did you succeed with a clean system? I am trying to figure out a good way to do this too haha.

1 Like

Hello, I know this topic is dead but I am very qualified to give a solid answer to this question.

Most of that network usage comes from how many parts get instantiated and replicated to the clients. The solution is to have the clients perform voxel destruction in a smart way:

  1. A destruction begins on the server side. Any parts that have never been divided but will be after this destruction are sent directly to the clients, who then create copies of each of them. The server continues to perform the destruction, and the resulting parts are placed in workspace.CurrentCamera which prevents these parts from replicating to clients, who are about to do their own voxel destruction. Sending over just the original parts is much cheaper than sending every part resulting from voxel destruction.
  2. Client performs the same destruction after creating their parts, this ensures the server and each client remain in sync

And that’s it. A nice bonus with this system is that you can keep StreamingEnabled true, and your parts will only flash if your server is extremely laggy (instead of all the time)

Feel free to just steal whatever you want from Shatterbox, my voxel destruction library.

This is how Shatterbox Client-Server algorithm works, and allows server side voxel destruction with extremely low network cost, as you can see here:

Hi, Thanks for all the replies guys. I completely forgot I was working on this system as I went on holiday (pretty much right after making the original post), and then moved onto other projects (I was only working on this system for fun). What you described in your reply is exactly what I did in my system, before I left. I haven’t taken a look at your system yet, I will do that soon and get back to working on my system, however some of the problems I encountered was syncing the newly destroyed parts with new clients which were joining, as well as dealing with unanchored parts. I can see (from the video) that your system does not unanchor floating parts, whereas my system creates welds between all voxels and sets the anchored state to false.
The problem I ran into was syncing the position of these unanchored parts with each client, as they individually have their own unanchored parts so it didn’t take very long for the positions to get out of sync.
StreamingEnabled was never a problem for me, even when I did voxel destruction with a size of 256x256x256 in a 1024x1024x1024 sized block. I hyper optimised my system to create the voxels very fast, however I failed to realise that the network was taking a massive hit, when I was making the system, I didn’t even bother opening the performance summary(whatever it’s called) and instead only looked at the microprofiler.
I plan to continue working on my system, so I’ll take a look at yours and see what I can improve on.