How to go about deleting loose parts not hit by explosions?

i have it so my explosions delete parts for performance and to reduce clutter everywhere, but i have an issue some parts that arent hit by the explosion will lose their welds and lie around until hit by another explosion. how would i detect these loose parts lying around to delete them?

1 Like

why wouldnt you just have all parts anchored

2 Likes

1 Like

So I just read about WorldRoot:GetPartBoundsInRadius. Perhaps before instancing your explosion you can use CollectionService to tag of the parts that are meant to be deleted by the explosions and clean up the stragglers after the explosion does its exploding.

1 Like

The problem is that they aren’t parts hit by the explosion, they’re parts outside the explosion connected to parts in the explosion that go loose

Okay, so if I understand correctly, it is a situation where like something like a hanging object will have a chain destroyed, leaving the hanging object lying around. There is a method GetConnectedParts which returns all objects connected to an object with a joint like a weld. It has a recursive option. I wonder if there is a way to identify the remaining loose objects with this, the instant the welds hit by the explosion break.

I am imagining this is a situation where a bunch of parts are welded together, so this might not be the most performant, but maybe it will lead you to something.

The key is discerning a list of connected parts that is “still standing” from a list of connected parts “gone loose”. You’ll have to design the criteria for that based on how you want the game to behave. There are a few sort of arbitrary differences between an Assembly that is a big castle wall and a huge chunk that gets knocked away: maybe the number of Parts in the Assembly, maybe the Mass, maybe whether the Assembly falls, it becomes up to you then.

Considering this has made me realize I’ve yet to see a game on the platform that “cleans up” little pieces.

2 Likes

Thanks a bunch I’ll look. Into that when I’m home :saluting_face:

1 Like

Unfortunately getconnectedparts doesn work :pleading_face: no clue what to try now

If you’re destroying the parts hit anyways is there a point of it all being unanchored and welded? Wouldn’t the point of having welds be to have the flying parts effect from the explosion or am i misunderstanding.

maybe just check past the blast radius after explosion using OverlapParams/AssemblyRootPart

example:

local function checkCloseParts(explosionPos, explosionRadius) 
	local checkRadius = explosionRadius + 5 --or wtv distance

	local params = OverlapParams.new()
	
	local nearbyParts =	game.Workspace:GetPartBoundsInRadius(explosionPos, checkRadius, params)
	local checked = {}
	
	for _, part in ipairs(nearbyParts) do
		local root = part.AssemblyRootPart
		
		if root and not checked[root] then
			checked[root] = true
			
			if not root.Anchored then
				local looseParts = root:GetAssemblyParts()

				for _, loosePart in pairs(looseParts) do
					if not loosePart.Parent then continue end
					
					loosePart:Destroy()
				end
			end
		end
	end
end

this should work because the AssemblyRootPart determines if an assembly of parts is anchored or not, think of it like a leader part that tells the other parts in the assembly what to do

so you check if the root is Anchored, and if not, then you get all the parts in the assembly (because they followed the leader and unanchored) and delete them because they would also be unanchored

destruction physics are one of the main features in my game im working on, debris parts are deleted after a couple of seconds

when you say “it doesn’t work” what does that mean? what did your implementation look like?

it just detects the parts that have already been hit by the explosion dont think theres much to do with that

that happens because by the time you go to check for that weld it’s already been destroyed by the explosion. one way to solve this is by making our own “explosion” so we have enough time to grab that relationship before it’s destroyed. it could look a little something like this,

local bomb = Instance.new("Explosion") -- your explosion object (you can set this up so whatever is producing your explosion, a tool, obstacle, etc. 
										-- by passing the explosion instance through this function before it is parented to workspace)
local sound = game.SoundService.explosion

local constraints = {
	"ManualWeld" -- you'll want to add the other types of "welds" or constraints you want the explosion to destroy here
}


-- you must pass your explosion through this function BEFORE it is parented to workspace
local function manualExplosion(explosion: Explosion, delayTime: number)
	
	local processedParts = {}

	-- fires once for every part the explosion hit
	explosion.Hit:Connect(function(hitPart, distance)
		if processedParts[hitPart] then return end
		
		sound:Play() -- playing the explosion sound manually cuz roblox don't wanna for some reason
		
		-- gets the entire "structure" of the hit part
		local assembly = hitPart:GetConnectedParts(true)

		for _, p in ipairs(assembly) do
			processedParts[p] = true

			-- break the welds manually now that we got all the parts we needed
			for _, joint in ipairs(p:GetJoints()) do
				if table.find(constraints, joint.ClassName) then
					joint:Destroy()
				end
			end

			-- apply our own "explosion" since our parts were welded during the initial blast
			local direction = (p.Position - explosion.Position).Unit
			local falloff = 1 - (distance / explosion.BlastRadius) -- explosion applies less force over distance
			p:ApplyImpulse(direction * explosion.BlastPressure * falloff)
		end

		-- set a delayed task so you still get the fallout from the blast
		task.delay(delayTime, function()
			for _, p in ipairs(assembly) do
				if p and p.Parent then p:Destroy() end
			end
		end)
	end)
end

-- pass the explosion through the function...
manualExplosion(bomb, 5)

wait(5)

-- mess around with these to find what u want
bomb.BlastRadius = 15
bomb.BlastPressure = 100

-- must set this to 0 otherwise it will not be able to grab the connected parts
bomb.DestroyJointRadiusPercent = 0

-- play the explosion by moving it where you want and parenting it to workspace
bomb.Position = game.Workspace.bombPosition.Position
bomb.Parent = game.Workspace

by disabling the explosions ability to destroy those welds, we can capture the entire structure of the parts that were actually hit, then simulate our own blast and cleanup the parts we want to (because we saved them prior to breaking the welds ourself). the code i provided is a little messy and unoptimized but it should get the general idea across,

do note, you will need to configure it a little to handle large structures like buildings that you probably don’t want to be completely vaporized after a small explosion, which can be done by taking the part/welds’ distance from the explosion into account and ignoring them instead.

1 Like

do you mean like to create a 2nd fake explosion to gather the parts before creating the real explosion? mb if i dont understand im tired

no no, you still use the same explosion, you just disable its ability to break anything because that stuff breaking is what prevents you from grabbing the connected parts. After you have the connected parts, you just apply a force to the parts within distance to mimic the explosion that should have already occurred. but because this all happens basically instantly, nobody’s any the wiser that it wasn’t a “real” explosion