Voxel Physics | An OOP user-friendly physics destruction module

Voxel physics is a brand new module designed to make voxel physics destruction like tearDown possible with just a line of code.

Here’s a list of the current features :

voxelizeHitbox

The core function of the module (the only one you need lol). This function works by taking as input a target (the part that you want to affect with physics) and a subtractor (the part that you want to subtract from the target). The crazy thing about this, is that by not giving any target input, the code will automatically find and subtract voxels in real time. There are also a smll library with custom effects that will affect the debris found, such as explosion and destroy. Here’s a showcase :

Registrazione 2024-05-01 174034

voxelizeAll

This function lets you completely voxelize totally any object given a target and a divider value (that will determine the number of voxels). This is not as useful as voxelizeHitbox. Still it can come handy in some situations

image

More showcases

Player that falls into different layer of wood.

Registrazione 2024-05-01 175910 (1)

This shows perfectly the voxelizeHtibox function in action

gianfragolo's Place_ 05012024_1 - Roblox Studio 2024-05-01 09-42-58

Final notes

This module was made entirely by @gianfragolo (me), but thanks to @Bartokens for inspiration. Also dont mind asking if you have any feedback/suggestion for this system, ill sure answer quickly since i dont have a life.

Here’s the link, almost forgot about it

23 Likes

Yo I was just thinking how it would be nice to find a physics destruction module, tysm

4 Likes

Thanks a lot! I really appreciate it man.

6 Likes

i dont know how to use it lol so this happened

1 Like

Can you show me your code please? so i can know if you did anything wrong. Also take a look at the test place so you can find a working version of this code.

2 Likes

so i thought it was fun to make the voxels smaller and change the script up a bit

local destruct = {}

destruct.debrisEffects = {}

destruct.debrisEffects[“Destroy”] = function(v)
v:Destroy()
end

destruct.debrisEffects[“Explode”] = function(v)
v.Anchored = false
v:ApplyImpulse(v.CFrame.LookVector * 1000)
end

function destruct.voxelizeAll(target, divider, anchor, velocity)
if target == nil then return end
if target:HasTag(“debris”) then return end

divider = divider or 2
anchor = anchor or false
velocity = velocity or 0

local newContainer = Instance.new("Model", workspace)
newContainer.Name = "container"

local Size = target.Size
local SizeX, SizeY, SizeZ = Size.X / divider, Size.Y / divider, Size.Z / divider
local selectedCorner = target.CFrame * CFrame.new(Size.X / 2, Size.Y / 2, -Size.Z / 2)

for x = 0, divider - 1 do
	for y = 0, divider - 1 do
		for z = 0, divider - 1 do
			local generatedPosition = CFrame.new(-SizeX / 2, -SizeY / 2, SizeZ / 2).Position + selectedCorner.Position + Vector3.new(-x * SizeX, -y * SizeY, z * SizeZ)            
			local newCube = Instance.new("Part", newContainer)

			newCube:AddTag("debris")
			newCube.Anchored = anchor
			newCube.CanCollide = true
			newCube.Size = Vector3.new(SizeX, SizeY, SizeZ)
			newCube.BrickColor = target.BrickColor
			newCube.Material = target.Material
			newCube.Position = generatedPosition
			newCube.Massless = true
			newCube:ApplyImpulse(newCube.CFrame.LookVector * velocity)
		end
	end
end

end

function destruct.voxelizeHitbox(target, subtract, params, divider)
if subtract == nil then return end

local new = setmetatable({}, destruct)

new.hitboxTouchedVoxel = require(script.Signal).new()
new.params = params or OverlapParams.new()
new.divider = divider or 8
new.touching =  {}
new.connection = nil

if target ~= nil then
	destruct.voxelizeAll(target, new.divider, target.Anchored, 0)
	target:Destroy()
	new.touching = workspace:GetPartsInPart(subtract, params)

	if #new.touching ~= 0 then
		for _,v in pairs(new.touching) do
			if v:HasTag("debris") then
				destruct.debrisEffects["Destroy"](v)
				new.hitboxTouchedVoxel:Fire(v)
			else
				destruct.voxelizeAll(v, new.divider, v.Anchored, 0)
				v:Destroy()
			end
		end
	end
else
	new.connection = game:GetService("RunService").Heartbeat:Connect(function(dty)
		new.touching = workspace:GetPartsInPart(subtract, params)

		if #new.touching ~= 0 then
			for _,v in pairs(new.touching) do
				if v:HasTag("debris") then
					destruct.debrisEffects["Explode"](v)
					new.hitboxTouchedVoxel:Fire(v)
				else
					destruct.voxelizeAll(v, new.divider, v.Anchored, 0)
					v:Destroy()
				end
			end
		end
	end)
end

return new

end

return destruct

1 Like

Ok but what did you change exactly? plus to make voxel smaller you just need to make bigger divider value : module.voxelizeHitbox(nil, subtract, nil, 8)

So is it better to use this over VoxBreaker?

2 Likes

The outcome depends on how effectively you utilize both, as they can be changed to fit the personality that best intends the project you’re working on.

6 Likes

The voxelizeAll function places the voxels in a random position rather than where the part was? Is that intended? I was under the assumption that what was supposed to happen was that the part which is being voxelized would have its Transparency set to 1 and its CanCollide set to false, then the generated voxels would occupy the exact same space after (and then you could add a Velocity to the voxels and it’d look like the wall was destroyed)? I think that’s what VoxBreaker does, at least.

Jujutsu Shenanigans ahh Physics

it dosent place them in random positions? It simply removes the original part, and sort of re-adds it as a bunch of cubes

When I tried it, the part was “rebuilt” but not in the same CFrame the original part was.