Part.Touched() not firing when it clearly is touching parts

I’m making a boss battle and one of the attacks is the boss launching a crate at the nearest player. The player can trigger a proximity prompt on said crate to launch the crate back at the boss. I also need the Crate to explode when it touches (almost) any part. Seems simple enough right?

Then how come the Crate.Touched isn’t firing when I can clearly see it hits me or a wall etc.

The part of the modulescript I have for the crate launching is as follows:

local CountGrim = workspace:WaitForChild("CountGrimula")


local humanoid = CountGrim:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")
local BezierTween = require(game.ServerScriptService.BezierTweens)
local Waypoints = BezierTween.Waypoints
local RepStore = game.ReplicatedStorage 
local BossItems = RepStore.BossItems

local TS = game:GetService("TweenService")

local Boss = {}

--...

Boss.FindClosestPlayerHRP = function()
	local hrp = CountGrim:WaitForChild("HumanoidRootPart")
	local closestHrp = nil
	local dist = 200
	for i, v in pairs(game.Players:GetPlayers()) do

		local tmpChar = v.Character or v.CharacterAdded:Wait()
		local tmpHrp = tmpChar:FindFirstChild("HumanoidRootPart")
		local tmpDist = (tmpHrp.Position - hrp.Position).Magnitude   
		--print("TmpDist = ", tmpDist)
		if tmpHrp and tmpDist < dist then
			closestHrp = tmpHrp
			dist = tmpDist
		end
	end
	return closestHrp
end

--...

Boss.CreateExplosion = function(Pos)
	local Hitbox = BossItems.Blast
	local Hit = Hitbox:Clone()
	local expand = TS:Create(Hit, TweenInfo.new(.5, Enum.EasingStyle.Linear), {Size = Vector3.new(12, 12, 12), Transparency = 1})
	
	local hitCon = nil
	hitCon = Hit.Touched:Connect(function(hit)
		hitCon:Disconnect()
		Hitbox.Spload:Play()
		if hit.Parent == workspace.CountGrimula then
			workspace.CountGrimula.Humanoid:TakeDamage(25)
			local scream = math.random(1, 3)
			if scream == 1 then
				Boss.PlaySound("Ooh", false)
			elseif scream == 2 then
				Boss.PlaySound("Ouch", false)
			elseif scream == 3 then
				Boss.PlaySound("Eugh", false)
			end
		elseif game.Players:GetPlayerFromCharacter(hit.Parent) then
			local Dmg = (10-(Hit.Size.X-2))/2
			hit.Parent:FindFirstChild("Humanoid"):TakeDamage(Dmg)
		end
	end)
	
	
	local Ex = Instance.new("Explosion")
	Ex.BlastPressure = 0
	Ex.BlastRadius = 0
	Ex.DestroyJointRadiusPercent = 0
	Ex.ExplosionType = Enum.ExplosionType.NoCraters
	Ex.Position = Pos
	Ex.TimeScale = 1
	Ex.Visible = true
	Ex.Parent = workspace.Despawnables
	expand:Play()
	
	local function Despawn()
		expand.Completed:Wait()
		if hitCon then
			hitCon:Disconnect()
		end
		Hit:Destroy()
		
	end
	
	task.spawn(Despawn)
end

Boss.LaunchCrate = function()
	local Crate = BossItems.Barrel
	local nCrate = Crate:Clone()
	nCrate.CFrame = CFrame.new(0.300000012, 15.9790001, -54.7999992, 0, 0, -1, 0, -1, 0, -1, 0, 0)

	local Waypoint1 = Vector3.new(0.300000012, 15.9790001, -54.7999992)
	--[[]] local plrcharhrp = Boss.FindClosestPlayerHRP()
	local Waypoint3 = Vector3.new((plrcharhrp.Position).X, 0, (plrcharhrp.Position).Z)
	--[[]] local midpoint = Waypoint1:Lerp(Waypoint3, .5)
	local Waypoint2 = Vector3.new(midpoint.X, (Waypoint1.Y)+5, midpoint.Z)
	local waypoints = Waypoints.new(Waypoint1, Waypoint2, Waypoint3)
	local Tween = BezierTween.Create(nCrate, {
		Waypoints = waypoints,
		EasingStyle = Enum.EasingStyle.Sine,
		EasingDirection = Enum.EasingDirection.In,
		Time = 2.5,
	})
	nCrate.Parent = workspace.Despawnables
	nCrate.spawnMagic:Play()
	nCrate.Effect.E1:Emit(2)
	nCrate.Effect.E2:Emit(2)
	task.wait(.5)
	--Boss.PlaySound("Barrel", true)
	Tween:Play()
	nCrate.whoosh:Play()
	
	local ProxPromptCon
	local CrateTouchCon
	
	ProxPromptCon = nCrate.ProximityPrompt.Triggered:Connect(function(plr)
		ProxPromptCon:Disconnect()
		Tween:Cancel()
		nCrate.ProximityPrompt:Destroy()
		local Waypoint21 = nCrate.Position
		local Waypoint23 = workspace.CountGrimula.Head.Position
		--[[]] local midpoint2 = Waypoint1:Lerp(Waypoint3, .5)
		local Waypoint22 = Vector3.new(midpoint2.X, (Waypoint23.Y)+5, midpoint2.Z)
		local waypoints2 = Waypoints.new(Waypoint21, Waypoint22, Waypoint23)
		local Tween2 = BezierTween.Create(nCrate, {
			Waypoints = waypoints2,
			EasingStyle = Enum.EasingStyle.Sine,
			EasingDirection = Enum.EasingDirection.In,
			Time = .1,
		})
		
		Tween2:Play()
		nCrate.Return:Play()
		nCrate.whoosh:Play()
	end)
	
	print("Check that this part of the script is running")
	CrateTouchCon = nCrate.Touched:Connect(function(hit) ----WHY IS THIS NOT WORKING?!?!?!?!?!?
		print("Crate has hit:", hit:GetFullName())
		if hit ~= workspace.Events.ArenaBarrier then
			CrateTouchCon:Disconnect()
			Boss.CreateExplosion(nCrate.Position)
			nCrate.Anchored = false
			nCrate.Transparency = 1
		end
		
	end)
end

--...


return Boss

As you can see from within the script, I am using the BézierTweeningn Module to launch the crate, but from what I understand, that shouldn’t affect Part.Touched .

I’ve even tried a while true do loop checking Part:GetTouchingParts() but it’s returning nothing.

I’ve read that raycasting is a solution many people use but that’s just checking for 1 particular part I thought and is extremely performance heavy.

Any solutions or workarounds?

1 Like

Am I just being stupid or isn’t this supposed to work?

1 Like

Here, nCrate.Touched:Connect(function(hit) needs to be all lowercase like this:
:connect(function(hit)

No, it’s supposed to be :Connect not :connect

nope, no difference sorry. plus it keeps changing back to capital C

Does your crate have the property CanTouch set to false?

nope

Ok, I finished making a ModuleScript that should be better than .Touched

-- Module Script
local module = {
	TouchStarted = {};
	TouchEnded = {};
}

function module.TouchStarted:Connect(Part:BasePart,func:any)
	local lastParts = workspace:GetPartsInPart(Part)
	
	coroutine.wrap(function()
		while task.wait() do
			local arg = {}

			for i, touching:BasePart in workspace:GetPartsInPart(Part) do
				if not table.find(lastParts,touching) then
					table.insert(arg,touching)
				end
			end
			lastParts = workspace:GetPartsInPart(Part)
			
			for i = 1, #arg do
				func(arg[i])
			end
		end
	end)()
end

function module.TouchEnded:Connect(Part:BasePart,func:any)
	local lastParts = workspace:GetPartsInPart(Part)
	
	coroutine.wrap(function()
		while task.wait() do
			local arg = {}

			for i, touching:BasePart in lastParts do
				if not table.find(workspace:GetPartsInPart(Part),touching) then
					table.insert(arg,touching)
				end
			end
			lastParts = workspace:GetPartsInPart(Part)

			for i = 1, #arg do
				func(arg[i])
			end
		end
	end)()
end

return module

This is how to use it

-- ServerScript
local Module = require(script.ModuleScript)

Module.TouchStarted:Connect(workspace.SpawnLocation,function(part:BasePart)
	print('Touch Started : ' .. part.Name)
end)

Module.TouchEnded:Connect(workspace.SpawnLocation,function(part:BasePart)
	print('Touch Ended : ' .. part.Name)
end)

Here’s a video showing what it does

Hope this helped!

1 Like

I’ll give it a go and get back to you

Probably create a seperate script for the touched event, then use a remote function or event and fire it inside the touched event so you can apply changes without having to create too much paths

nope this didn’t work, GetTouching Parts is returning an empty table at all times

It’s not supposed to return a table, it returns a part.

it’s supposed to return a table of parts

???

What it does is that it will loop through the table then call the function with the value in the table

But if you want to make it just return a table, then replace the for loop with

func(arg)

Edit : This is the for loop im talking about

Oh, yeah, but I’m printing the table print(part:GetTouchingParts()) and it’s empty

Is CanCollide off? You should use workspace:GetPartsInParts()

Also, if you use it like

local parts = Module.TouchStarted:Connect(part)

That’s not how it works, this is how

Module.TouchStarted:Connect(part,function(otherpart)

end)

The crate has CanCollide = false CanTouch = true CanQuerey = true Anchored = true

doesn’t that only include primitive parts? I need it to detect meshparts and unions too.

The :GetTouchingParts() doesn’t work on parts without a TouchInterest. Add this before :GetTouchingParts()

part.Touched:Connect(function() end)