Bullet object .Touched event only triggering on rigs, not anything else (issue)

Alright, so I have an enemy that shoots a simple gun that creates a bullet that travels a bit slow (because I wanted to add parrying) and uses tweens to move (the tweens use a magnitude-based tweeninfo so they always move at a constant speed).
The issue I’m having though is that for some unknown reason, the bullets refuse to take .Touched events from anything but a player character/rig (models don’t work either). It works perfectly fine on the prior mentioned rigs, but just not parts. I searched for a bit and couldn’t find a solution (but did find some poor bloke who had the same issue on reddit and had no one reply) and ended up turning to here.
All I’ve really tried was just tweaking how it interprets the .Touched event, though I am now to believe it is with the event itself, not how I’m interpreting it. I was going to try something like :GetPartsInPart, but couldn’t really figure out how to apply that to an event. Any help would be appreciated.

Script:

local ts = game:GetService("TweenService")

--variety is nice.
local firesounds = {
	script.Parent["Goblin Flintlock"].Handle.Fire,
	script.Parent["Goblin Flintlock"].Handle.Fire2
}
--going to be used for reloads, useless atm
local flintsounds = {
	script.Parent["Goblin Flintlock"].Handle.M1,
	script.Parent["Goblin Flintlock"].Handle.M2
}

local shootanim = script.Parent.shootanim
local shoottrack = script.Parent.Humanoid.Animator:LoadAnimation(shootanim)

local bullet = game.ReplicatedStorage.fpbullet
--just for ease of use to change how fast the bullet goes, is a bit slower than what it'll be so I could test easier
local bulletspeed = 5

function shoot(target)
	shoottrack:Play()
	--used by the animation i made
	shoottrack:GetMarkerReachedSignal("Fire"):Connect(function()
		local firesound = firesounds[math.random(1,table.maxn(firesounds))]
		firesound:Play()
		
		--getting target positon for tween
		local lookat = CFrame.lookAt(script.Parent["Goblin Flintlock"].Handle.Position,target.HumanoidRootPart.Position)
		local tweentarg = script.Parent["Goblin Flintlock"].Handle.Position + (lookat.LookVector * 10000)
		
		local goal = {}
		goal.Position = tweentarg
		
		local clone = bullet:Clone()
		clone.Parent = workspace
		clone.Position = script.Parent["Goblin Flintlock"].Handle.Position
		clone.Anchored = true
		
		--tweeninfo calculated via magnitude (fancy!)
		local tween = ts:Create(clone,TweenInfo.new((tweentarg - script.Parent["Goblin Flintlock"].Handle.Position).Magnitude / bulletspeed),goal)
		
		tween:Play()
		
		-- this event has ruined me lol
		clone.Touched:Connect(function(o)
			clone:Destroy()
			if o.Parent:FindFirstChild("Humanoid") and o.Parent:FindFirstChild("Humanoid") ~= script.Parent.Humanoid then
				o.Parent:FindFirstChild("Humanoid"):TakeDamage(500/(clone.Position - script.Parent.HumanoidRootPart.Position).Magnitude)
			end
		end)
		--if the distance is covered without ever hitting anything
		tween.Completed:Connect(function()
			if clone then
				clone:Destroy()
			end
		end)
	end)
end
--just testing it
wait(5)

shoot(workspace.DecepticonLucas)

wait(5)

shoot(workspace.DecepticonLucas)

wait(5)

shoot(workspace.DecepticonLucas)

(it’s a work-in-progress script so some variables may be useless right now, so sorry for that)
(also I am a messy code maker, so double sorry)
(also also this is my first ever post so i might’ve messed something up, so actually triple sorry)

edit: tools also collide with it for some reason

2 Likes

.Touched events are notoriously unreliable on anything other than slow moving or stationary projectiles. I tend to use CFrame projectiles every heartbeat and use a raycast to check for anything immediately in front of it to detect a hit.

After a couple attempts I actually got this to work decently well! Only problems I have had is a bit of delay, but that might just be because of how I did the loop since I’m unsure if RunService.Heartbeat is better on performance or if while task.wait() do is instead. If anyone was having the same problem as me and had a bit more difficulty with it then here’s the code I used for it eventually! (the script is now within the bullet object, and the bullet object is now parented to the rig instead)

local dmgdropoff = script.Parent.dmgdropoff.Value
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = script.Parent.Parent:GetDescendants()

while task.wait() do
	local ray = workspace:Raycast(script.Parent.Position,script.Parent.CFrame.LookVector,params)
	if ray then
		if ray.Instance.Parent:FindFirstChild("Humanoid") ~= script.Parent.Parent.Humanoid then 
			if ray.Instance.Parent:FindFirstChild("Humanoid") then
				ray.Instance.Parent:FindFirstChild("Humanoid"):TakeDamage(dmgdropoff*100/(script.Parent.Position - script.Parent.Parent.HumanoidRootPart.Position).Magnitude)
			end
			break
		end
	end
end

script.Parent:Destroy()

(also thanks for helping me with this baddad)

1 Like

One issue I had with projectiles was to make sure any loops associated with them were stopped when the projectile was destroyed. I suggest adding something to you while task.wait() do loop to detect when the projectile is no longer in the workspace and break the loop. There again I do use a single script to control all projectiles.

Since the script is parented to the bullet object itself, and the bullet destroys itself when hitting something/reaching the end of it’s tween, I thought that’d automatically break the loop since the script the loop is within doesn’t exist. Is that not how it works? I’m not very into the fine workings of how scripts run.

edit: actually nevermind this I’m pretty sure you were just talking about your issues sorry

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.