Question about making memory-efficient data structures

Hi! I’m making a game that has voxel-like building mechanics and I want to optimize the game as much as possible for mobile.

Each voxel only has a small amount of information. If I were to compact all of this information into a single byte and make custom getters and setters to be able to read and write to that byte would that be a smart memory efficient thing to do? It seems like a lot of voxel tutorials don’t do this and I’m unsure why.

Thank you

Frankly, it’s because that’s approaching a needless optimization unless you’re targeting a very high voxel density or extremely low-spec hardware. When I say low-spec, I mean "pushing up against the limits of what Unity is even supported on.

Make a basic voxel implementation first and optimize from there instead. This is premature optimization and possibly needless in the first place.

2 Likes

Very hard to estimate this without the whole project at hand. What does the part where the voxels are baked into a mesh look like? That’s usually the painpoint of voxel systems.
Smaller memory footprint can help when iterating through the whole data structure, but it might not be curicial.
Tutorials however will surely not do it just for the sake of simplicity.

By the way, are you designing the system compatible to Burst and the Job system already?
That is the most significant performance improvement one can get in Unity (and requires design decisions made relatively early).

Before you start optimizing, you’ll need to actually hit a problem that requires said optimization. And it looks like you have not encountered this problem yet.

Let’s say you’re using a voxel block with size of 64. 64x64x64. If you use a single byte per voxel, that’s 262144 bytes. If you use an int, that’s 1048576.

The thing is, this is not a huge amount of memory on a modern system.

Basically, realistically speaking in the long run you’ll likely be far more concerned with skipping voxels you do not need to process. Because while 262144 voxels is not a lot of RAM, just iterating through all of them is 262144 operations which can be noticeable.

So in the long term you’re likely going to need to optimize for speed and not memory.

For practical example, imagine that your voxel grid is a cube with edge length of one thousand kilometers, and one voxel is a 1 meter cube. And you need to build a mesh out of that.

You can’t iterate through all of this, because that’s 1000000^3 cubes, and if, for example, one voxel is processed in a millisecond, that’ll take 30 million years.

So what are you going to do? You’ll introduce a hierarchical structure like an octree ( Octree - Wikipedia ) that will be able to quickly report if every child node is empty or full. Most of this huge voxel grid will be either comletely empty or completely solid, and as a result will not require processing of a mesh.

Likewise, in the same fashion that it’ll take 30 million years to process something this huge, you can’t store it in ram uncompressed, because it will take one thousand petabytes. The hierarchical structure will ALSO handle that. The size of data can be vastly reduced if you only store blocks that are not all set to the same value, or if the world is defined with a procedural function, and only stores alteration of that function. That’s pretty much how minecraft does it. Because the world is huge, the player is never going to be able to change it all, as a result only tiny part of it that player alters is stored to the disk.

But. Like @Murgilod correctly said, messing with something like this only makes sense if you want HUGE voxel grids capable of storing cities or planets. At lower scale, while experimenting, you can be fine with an uncompressed blocks.

For starters, tutorials are designed for the lowest common denominator which is a complete beginner who will have little knowledge beyond the basics of the engine. Concerning the question itself the answer is definitely that it would save memory but memory is rarely the actual problem here. Instead the problem is storage.

Minecraft has a very optimized approach to storing its world. It creates a “palette” where each entry is unique and then the blocks in the chunks reference these entries. If you had a block of all stone, for example, the palette would have a single entry for the stone and then all the blocks would point at that.

That said even with that optimization there are so many blocks in a world that it’s very easy for a world to swell to large sizes. We’re talking gigabytes of data. Minecraft Pocket Edition has the limitations it does because if it didn’t you would easily fill up the storage on a phone.

https://gaming.stackexchange.com/questions/263816/what-is-the-average-disk-storage-size-of-a-minecraft-chunk