When I run the game “From the Depths” on my computer, I build ships that can consist of thousands of blocks and the game will run smoothly with very minimal frame drops and lag. When I tried to make a similar game in Unity, when spawning the ship it lags more that anything I have ever seen before and my frame rate tanks. How did they do that without causing the their game’s frame rate to tank?
I think the reason that my game lags is due to way too many colliders. With that in mind is there any way to combine colliders from the many blocks into 1 collider?
Are you creating a separate GameObject for each block? That would be really slow.
I don’t know any details about how From the Depths was made, but I imagine they generate a single, optimized mesh from all of the blocks.
This should work well in Unity if you combine all of the blocks into a single mesh and make the ship one single GameObject. The Unity API includes classes that you can use to write code to combine meshes or even construct your own meshes during run-time.
The blocks in from the depths are destructable. When hit by a projectile from any enemy ship they can break off of the ship they were attached to. With that said how would I combine meshes like what you said and still make them destructable? What if I were only to combine the colliders but make it to where the blocks can still fall off (or be destroyed with Destroy())?
If you’re building things out of cubes, then you should research “Voxels”. Minecraft, for example, allows you to create and destroy blocks at will, and it continually recreates its combined meshes as it goes.
There was once a thread on this forum about how Minecraft is optimized and how you would implement it Unity, which might find interesting.
Ok, so if I were to combine all the blocks into one big mesh, how can I get it to where when the ship is hit by a projectile the part of the mesh that was hit is disabled (Or made invisible)?
As I understand it, in a voxel system, the cubes are stored in some sort of data structure (not the mesh data itself, but the type of cube and its location in the overall voxel grid, stored in a 3-dimensional array or something like that). You would build your mesh based on this data structure.
So when your ship is hit, you would need to write some code to map the physical location to corresponding location in the voxel grid and then deactivate that cube. Then you would rebuild the mesh based on the updated voxel grid. I’m sure there is a way to optimize the process so that you can update the existing mesh, rather then recreate it, but I don’t know what that would be.
Right, the reason Lanefox and I are suggesting that you research Voxels is this sort of thing is probably too complicated to be answered in a simple forum thread.
Divide your world into chunks of blocks, each having a mesh. When a block is changed, iterate the new blocks and rebuild the mesh. It’s actually quite fast even with large chunks. Of course, there are a ton of considerations beyond this which will depend on what you want in your game. This includes how big your world should be and the sorts of interactions you want to support with your blocks.
For your ship, just have air voxels that don’t contribute to the mesh. Replace the hit area with air blocks and rebuild the mesh.
Once a ship is combined into a mesh how would I go about disabling the blocks in the mesh when hit? By the way… The ship building system is more than just blocks, but has different shapes and different sizes: Check my playlist specifically the last few videos to get what I mean:
So, what you have will probably enhance performance, but the combined mesh will still waste a lot of rendering time because it will be full of hidden faces that are on the inside of the boat.
The second problem is that now you have no way to determine what vertices used to be part of the block that was hit.
This is why I recommended studying voxels. A voxel implementation will solve these problems.
OP, this topic is MASSIVE. And any system you develop to do it is going to be something that spans more than just a simple script.
Unity is not designed as a voxel engine. It can ‘do’ them technically, but that’s a heavy modification of the existing system. This is why games like Minecraft use their own self built engine (and is still kind of slow at what it does… hence the simplicity of its visuals).
But yeah, when everyone keeps saying “research”… they’re not saying go read an article. They’re saying… research. Like proper long form sit down and spend days studying something, as well as studying any foundational topics that you might need to understand the topic you’re initially studying.
the game’s steam page said that the ships is indeed voxel
simply put, voxel it self is only 3d grid based data so you still need some way to represent/visualize it. minecraft uses cube to represent the voxel but imho the game you mentioned seems to use marching cube…
Is there any way to just simply combine all the blocks into one mesh with a collider and delete part of the mesh when hit? I have tried to use voxels but remember the ship uses parts that not always cubes but can come in many different shapes. Cannons are by no way cube shaped.
If you look at @bart_the_13th 's post. just above yours, he’s already mentioned that a voxel does not need to be a cube necessarily. In addition, there’s no reason that you can’t have objects like cannons handled separately from the voxel system, if you feel like they don’t fit.
Edit: I guess another thing you can try is to use a sphere collider to represent the damage. Calculate which vertices intersect the sphere and delete them from your mesh. I’m not sure how you’d smooth that out when you’re done, though.
If you haven’t already, google “Unity procedural mesh” with no quotes to find info about making changes to a mesh object through code.
Note that SetPass calls after combination does NOT decrease, so there won’t be any benefits in doing so, except decreasing number of GameObjects.
Bonus: GPU instancing won’t work as well, since combined mesh would actually be a ton of submeshes.
Best solution in this case is to use CommandBuffer.DrawMeshInstanced, to draw up to 1023 (or more if I recall beta patch notes correctly?) meshes per batch.
Also, yeah. Voxels. There’s already a bunch of solutions for that on the Asset Store.
Also, there’s ECS approach. I bet it will save a ton of performance when jobs / burst are used with .DrawMeshInstanced.
Is that right? Even using Unity’s built-in Mesh.CombineMeshes script there is an option to merge all of the meshes that you combine into a single submesh. What I had in mind was combining meshes to a single submesh with a single material.