VoxBreaker | An OOP Voxel Destruction module

Hello, I need some help regarding adding a body velocity to a debris/blocks. I want to make something where if the hitbox hits a wall, the debris/blocks gets knocked away using body velocity. Although there is a problem. It seems like smaller parts gets slid away, and it doesn’t slide for larger parts. I want smaller parts to not get slid away after the BodyVelocity gets destroyed

1 Like

Can you give an example about this one?, im still confusing about this since i can’t unanchor voxels on server script

Increase the velocity and lower the duration of the bodyVelocity. Bigger parts have more mass and thus will not travel aa far

2 Likes

W and Peak module!, two questions question tho, how could make so any specific parts can be voxelized?, or what you did in your skills/abilities ?, would i need to set the destruction individually?

and how could i make so when you voxelize a part, the player will go smoothly between that parts?, like the character going throught a wall?

theres a attribute in the part called Destroyable i think and its a boolean one and if that is checked true then that part will become voxelized

1 Like

All parts with the attribute “Destroyable” with a boolean value of true will be checked. You can change the name of the attribute in the module settings. So yeah, you have to individually mark every part that you want to be voxelized.

And for your second question, I explained that in this post:

1 Like

Alright, i got it to work, but now in the client, how would i set all the voxelized parts to be blown or separated after being destroyed on the server?

just clone and unanchor them on the client. Then use any method you’d like for moving them. I personally use bodyVelocity

1 Like

Okay

local moveable = voxBreaker.CreateMoveableHitbox(3,20,Vector3.new(5,5,5),CFrame.new(),Enum.PartType.Ball)
moveable:Start()
local connection
local touched = {}
connection = moveable.Touched:Connect(function(Parts)




	for i,v:Part in pairs(Parts) do
		v.Parent = script
	end

	Remote:FireAllClients(Parts,Character.Instance.HumanoidRootPart.Velocity/2)

	for i,v:Part in pairs(Parts) do
		if table.find(touched,v) == nil then
			v:Destroy()
			table.insert(touched,v)
		end
	end
end)

while true do
	moveable.Part.Position = Character.HumanoidRootPart.Position + Character.HumanoidRootPart.Velocity / 12 
	task.wait()
end

Can i know why are you doing

Character.Instance.HumanoidRootPart.Velocity/2

When sending the information to the client?, and also, why u insert the parts to the table?, just wanna know if i am missing something :sweat_smile:

This is my server

game.ReplicatedStorage.RemoteEvent.OnServerEvent:Connect(function(player)
	local char = player.Character
	local VoxBreaker = require(game.ReplicatedStorage.VoxBreaker)
	local Size = Vector3.new(10,10,10)
	local Cframe = char.HumanoidRootPart.CFrame
	local Shape = Enum.PartType.Ball
	local MinimumSize = 3
	local Seconds = 5

	local Voxels = VoxBreaker:CreateHitbox(Size,Cframe,Shape,MinimumSize,Seconds)
	for i, v in pairs(Voxels) do
		game.ReplicatedStorage.RemoteEvent:FireAllClients(v, player.Character)
		v:Destroy()
	end
	
end)

And client

local uis = game:GetService("UserInputService")

uis.InputBegan:Connect(function(input,gpe)
	if gpe then return end
	if input.KeyCode == Enum.KeyCode.E then
		game.ReplicatedStorage.RemoteEvent:FireServer()
	end
end)

game.ReplicatedStorage.RemoteEvent.OnClientEvent:Connect(function(part, specificSpawnPart)
	local cloneit = part:Clone()
	cloneit.Parent = workspace.debrisfolder
	cloneit.Anchored = false
	cloneit.CanCollide = true
	cloneit:PivotTo(specificSpawnPart:GetPivot())
end)

i found a error too

Workspace.SanJoseYTXD.LocalScript:11: attempt to index nil with ‘Clone’ - Client - LocalScript:11
14:51:55.182 Stack Begin - Studio
14:51:55.182 Script ‘Workspace.SanJoseYTXD.LocalScript’, Line 11 - Studio - LocalScript:11
14:51:55.182 Stack End

1 Like

have question yk how i could add in velocity to the model so like if its velocity is over 30 and then it will create the hitbox

you have to parent the voxels to replicated storage before sending a remote event

im not sure if its the same problem I had but in the server right before you fire the remote to clients you should do

task.wait()

or if you want it to be cleaner

				if math.random(1,2) == 2 then
					task.wait()
				end
1 Like

ok nvm i found how to do it.:+1:

It seems like I have discovered the problem. The reason why the BodyVelocity does not stop because it does not get destroyed for some reason.

This is the code that I’m using:

local module = {}

function module.StartMovable(params)
	
	local Size = params['Size']
	local Cframe = params['Cframe']
	local Shape = params['Shape']
	local part = params['part']
	local Timer = params['Timer']
	local KB = params['KB']
	local DIR = params['DIR']
	
	local VoxBreaker = require(game.ReplicatedStorage.Scripts.Modules.VoxBreaker)
	
	local PART = Instance.new('Part', part)
	PART.CanCollide = false
	PART.Massless = true
	PART.Transparency = 1
	
	
	local w = Instance.new('Weld', PART)
	w.Part0 = part
	w.Part1 = PART
	w.C0 = Cframe

	local Voxels = VoxBreaker.CreateMoveableHitbox(4, 20,Size,Cframe,Shape)
	Voxels:Start()
	Voxels:WeldTo(PART)
	
	local connection
	connection = Voxels.Touched:Connect(function(Parts)


		


		for i,v:Part in pairs(Parts) do
			
				v.Anchored = false
				
					
				if KB and not DIR then
					local NODIRBV = Instance.new("BodyVelocity")
				NODIRBV.MaxForce = Vector3.new(100000,100000,100000)
				NODIRBV.Velocity = KB
				NODIRBV.Parent = v

					delay(0.4, function()
					NODIRBV:Destroy()
					end)
				else
					local dir = CFrame.new(part.CFrame.p, v.CFrame.p).LookVector
					local DIRBV = Instance.new("BodyVelocity")
				DIRBV.MaxForce = Vector3.new(100000,100000,100000)
				DIRBV.Velocity = dir * KB
				DIRBV.Parent = v

				delay(0.4, function()
					DIRBV:Destroy()
				end)
				end
				
				
				
				
				
				
				
			
		end
	end)
	
	delay(Timer, function()
		Voxels:Destroy()
		PART:Destroy()
		
	end)
end

return module

2 Likes

hello, does anyone know any method to make my script send the parts to a client to be able to debris? that in the server only delete the parts that the hitbox touched and those parts are sent to the client to debris, I can’t find any way to do it.

game.ReplicatedStorage.RemoteEvent.OnServerEvent:Connect(function(player)
	local char = player.Character
	local VoxBreaker = require(game.ReplicatedStorage.VoxBreaker)
	local Size = Vector3.new(10,10,10)
	local Cframe = char.HumanoidRootPart.CFrame
	local Shape = Enum.PartType.Ball
	local MinimumSize = 5
	local Seconds = 5
	
	local touched = {}
	local Voxels = VoxBreaker:CreateHitbox(Size,Cframe,Shape,MinimumSize,Seconds)
	for i, v in pairs(Voxels) do
		if table.find(touched,v) == nil then
			
	
		
			table.insert(touched,v)
			game.ReplicatedStorage.Voxels:FireAllClients(v,Cframe,Seconds)
			task.wait()
		v:Destroy()
	
	
		end
	
		
	end
end)

UPDATE

Test place has been updated

I have attempted to incorporate partCache like a few suggested, but for some reason, the performance is even worse than before. My implementation of the system is probably bad, so if anyone else wants to try and figure out partCache for the module then you are free to do so. I’ve spent well over 7 hours trying to implement it and It just isn’t working well enough to be usable. You can download the version of the module with partCache here:
PartCacheVoxBreaker.rbxm (17.3 KB)

very cool man im now interested on whats coming for the future of this module

one problem i see sometimes happens is if theres multiple voxel parts idk their name the ground becomes transparent and you can phase thru it

what seems to work best performance wise for me is destroying the voxels on the sever, sending the voxel table to the client, but instead of directly cloning the voxels i just used partcache to create a new part and clone all of the voxel’s properties

this only gave me lag on large scale destruction as expected

The intention with part cache is to completely remove the need to clone or destroy parts on the server. Doing it your way might improve performance, but not significantly enough to be worth it. (Im assuming)