How to Destroy a Part When it Touches a Part During a Animation

I have a sword that is supposed to break a window when they click to trigger the sword to attack. The thing is I have no idea how to check if the sword is touching the window and if they use the animation at a certain time.

Sword Local Script:

local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local tool = script.Parent
local hold = tool:FindFirstChild('Hold')
local attack = tool:FindFirstChild('Attack')
local animationtrack = char:WaitForChild('Humanoid').Animator:LoadAnimation(hold)

tool.Equipped:Connect(function()
	animationtrack.Looped = true
	animationtrack:Play()
end)

tool.Unequipped:Connect(function()
	animationtrack:Stop()
end)

tool.Activated:Connect(function()
	animationtrack:Stop()
	local animationattack = char:WaitForChild('Humanoid').Animator:LoadAnimation(attack)
	animationattack:Play()
	wait(0.78)
	tool["Sword Swing Metal Heavy"]:Play()
	animationattack.Stopped:Wait()
	animationtrack:Play()
end)


Door Server Script:

local plrenter = script.Parent.PlayerEnter

local door = {}

function door.open(doorModel, number, plr)
	doorModel:SetAttribute("Open", true)
	local amountofshards = math.random(4,10)

	doorModel.Window['glass shatter']:Play()
	for i,v in pairs(doorModel.Window.Window:GetChildren()) do
		if v:IsA('BasePart') or v:IsA('UnionOperation') then
			v:Destroy()
		end
	end
	for i = 1, amountofshards do
		local clone = game.ReplicatedStorage.Shard:Clone()
		clone.Parent = workspace.Fx
		local Yscale = math.random(1,5)
		local Zscale = math.random(1,5)

		clone.Size = Vector3.new(0.05, Yscale, Zscale)

		clone.Position = doorModel.ShardsSpawn.Position
		game.ReplicatedStorage.Remotes.TextEffect:FireClient(plr, clone)
		game.Debris:AddItem(clone, 60)
		i += 1
		
	end
	for i,v in pairs(doorModel.Window.CrackedWindow:GetChildren()) do
		if v:IsA('BasePart') or v:IsA('UnionOperation') then
			v.Transparency = 0
		end
	end
	local CollectionService = game:GetService("CollectionService")
	for i,v in pairs(workspace.Fx:GetChildren())do
		if v.Name == "Shard" then
			CollectionService:AddTag(v, "Currency")
		end
	end
	plr.PlayerGui.MainGui.TextLabel.Text = tostring(tonumber(plr.PlayerGui.MainGui.TextLabel.Text) + amountofshards)
	plrenter:Fire(number)
end
function door.new(roomModel, number, locked)
	local doorModel = workspace.Door:Clone()

	doorModel:PivotTo(roomModel.Exit.CFrame)
	doorModel:SetAttribute("Open", false)

	doorModel.WindowNumber.SurfaceGui.TextLabel.Text = string.format('%04d', number)
	if locked == true then
		doorModel.WoodBoard["Meshes/Planks_Cube.001"].ProximityPrompt.Enabled = true
		doorModel.WoodBoard2["Meshes/Planks_Cube.001"].ProximityPrompt.Enabled = true
		for i,v in pairs(doorModel.WoodBoard:GetChildren()) do
			if v:IsA('BasePart', 'UnionOperation') then
				v.Transparency = 0
				v.CanCollide = true
			end
		end
		for i,v in pairs(doorModel.WoodBoard2:GetChildren()) do
			if v:IsA('BasePart', 'UnionOperation') then
				v.Transparency = 0
				v.CanCollide = true
			end
		end
	end


	doorModel.WoodBoard["Meshes/Planks_Cube.001"].ProximityPrompt.PromptButtonHoldBegan:Connect(function(plr)
		if plr.Character:FindFirstChild('Crowbar') then
			doorModel.WoodBoard["Meshes/Planks_Cube.001"]["Destroying A Car Crowbar 5 (SFX)"]:Play()
			local hum = plr.Character:FindFirstChild('Humanoid')
			local track = hum.Animator:LoadAnimation(workspace.Items.Crowbar.Handle.Use)
			track.Looped = true	
			track:Play()
		end
	end)

	doorModel.WoodBoard["Meshes/Planks_Cube.001"].ProximityPrompt.PromptButtonHoldEnded:Connect(function(plr)
		doorModel.WoodBoard["Meshes/Planks_Cube.001"]["Destroying A Car Crowbar 5 (SFX)"]:Stop()
		local hum = plr.Character:FindFirstChild('Humanoid')
		for _,anim in pairs(hum.Animator:GetPlayingAnimationTracks()) do
			if anim.Name == "Use" then
				anim:Stop()
				break
			end
		end
	end)

	doorModel.WoodBoard2["Meshes/Planks_Cube.001"].ProximityPrompt.PromptButtonHoldBegan:Connect(function(plr)
		if plr.Character:FindFirstChild('Crowbar') then
			doorModel.WoodBoard2["Meshes/Planks_Cube.001"]["Destroying A Car Crowbar 5 (SFX)"]:Play()
			local hum = plr.Character:FindFirstChild('Humanoid')
			local track = hum.Animator:LoadAnimation(workspace.Items.Crowbar.Handle.Use)
			track.Looped = true
			track:Play()
		end
	end)

	doorModel.WoodBoard2["Meshes/Planks_Cube.001"].ProximityPrompt.PromptButtonHoldEnded:Connect(function(plr)
		doorModel.WoodBoard2["Meshes/Planks_Cube.001"]["Destroying A Car Crowbar 5 (SFX)"]:Stop()
		local hum = plr.Character:FindFirstChild('Humanoid')
		for _,anim in pairs(hum.Animator:GetPlayingAnimationTracks()) do
			if anim.Name == "Use" then
				anim:Stop()
				break
			end
		end

	end)

	doorModel.WoodBoard["Meshes/Planks_Cube.001"].ProximityPrompt.Triggered:Connect(function(plr)
		if plr.Character:FindFirstChild('Crowbar') then
			for i,v in pairs(doorModel.WoodBoard:GetChildren()) do
				if v:IsA('BasePart' or 'UnionOperation') then
					v.Anchored = false
					v.CanCollide = false
				end
			end
			doorModel.WoodBoard["Meshes/Planks_Cube.001"]["Wood break 1"]:Play()
			wait(1)

			doorModel.WoodBoard:Destroy()

			if not doorModel:FindFirstChild('WoodBoard2') then
				if plr.Character:FindFirstChild('Crowbar') then
					plr.Character:FindFirstChild('Crowbar'):Destroy() 
				elseif plr.Backpack:FindFirstChild('Crowbar') then
					plr.Backpack:FindFirstChild('Crowbar'):Destroy()
				end
			end
		end	

	end)

	doorModel.WoodBoard2["Meshes/Planks_Cube.001"].ProximityPrompt.Triggered:Connect(function(plr)
		if plr.Character:FindFirstChild('Crowbar') then
			for i,v in pairs(doorModel.WoodBoard2:GetChildren()) do
				if v:IsA('BasePart' or 'UnionOperation') then
					v.Anchored = false
					v.CanCollide = false
				end
			end
			doorModel.WoodBoard2["Meshes/Planks_Cube.001"]["Wood break 1"]:Play()
			wait(1)
			doorModel.WoodBoard2:Destroy()
			if not doorModel:FindFirstChild('WoodBoard') then
				if plr.Character:FindFirstChild('Crowbar') then
					plr.Character:FindFirstChild('Crowbar'):Destroy() 
				elseif plr.Backpack:FindFirstChild('Crowbar') then
					plr.Backpack:FindFirstChild('Crowbar'):Destroy()
				end
			end
		end
	end)


	doorModel.Hitbox.Touched:Connect(function(hit)
		local humanoid = hit.Parent:FindFirstChild('Humanoid')
		if humanoid and doorModel:GetAttribute('Open') == false and humanoid.Parent:FindFirstChild('Rock') then
			if not locked then
				local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
				door.open(doorModel, number, plr)
			end
			if locked then
				if not doorModel:FindFirstChild('WoodBoard') and not doorModel:FindFirstChild('WoodBoard2') then
					local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
					door.open(doorModel, number, plr)
				end
			end
		end
	end) 
	
	local binable = Instance.new('BindableEvent')
	binable.Event:Connect(function()
		if doorModel:GetAttribute('Open') == false then
			if not locked then
				door.open(doorModel, number)
			end
		end
	end)
	binable.Name = 'OpenEvent'
	binable.Parent = doorModel



	doorModel.Parent = roomModel


	return doorModel
end



return door

In this script the sword is named “Rock”

Video:
robloxapp-20230515-2133277.wmv (1.1 MB)

1 Like

An approach a lot of games use is to use a hitbox that spawns at a certain keyframe of an animation. Just check when the animation reaches the keyframe that matches the attack of the sword, use a GetPartBoundsInBox query to check for the window, and if it’s there, break it.

You can always attach a Touched event to the sword, but this is finnicky in my opinion.

EDIT: Don’t use Shapecasts, as they do not cast for already-colliding Instances, which won’t help you in this case. My apologies!

1 Like

Can you give me a example of how to use :GetPartBoundsInBox? I understand what you mean by the hitbox spawning, but how would I implement the GetPartBoundsInBox

Also, I don’t think the hitbox is needed on the sword because the door already has a hitbox inside of it.

1 Like