Weird .Touched() Errors with a Part

Hey developers!

I was trying to make a Raycast with my tool and whenever the ray hits something it will check if it’s a Part and if it is it will destroy it. Now sometimes this works, but sometimes it doesn’t. I’ve tried printing out everything that touched my ray (bullet) but in the end sometimes it prints out the part. Sometimes it doesn’t.

I don’t know if this is a bug or something so I’ve came here.

This is my ray/bullet touched script:
local origin = shootPart.Position
local direction = (position - origin).Unit * 300
local result = Workspace:Raycast(origin, direction)

local intersection = result and result.Position or origin + direction
local distance = (origin - intersection).Magnitude

local bullet = Instance.new("Part")
bullet.Anchored = true
bullet.Size = Vector3.new(0.1, 0.1, distance)
bullet.CFrame = CFrame.new(origin, intersection)*CFrame.new(0, 0, -distance/2)
bullet.Parent = Workspace
bullet.BrickColor = BrickColor.new(0, 143, 156)
bullet.Material = Enum.Material.Neon

-- Later in the script

bullet.Touched:Connect(function(hit)
	print(hit.Name)
	if hit.Name == "SpecialPart" then
		hit:Destroy()
	end
end)

-- Btw for the part creator i added a name
newPart.Name = "SpecialPart"

This is what it looks like in game:

Lol almost a perfect loop

Before you comment about region3’s, I already tried to use them but they don’t work aswell for some reason.

Any ideas? Thanks in advance!

3 Likes

can’t you just check for the part with :FindPartOnRay??

1 Like

The old :FindPartOfRay() method was deprecated, and it isn’t good practice at all to use deprecated methods.

1 Like

Haven’t really used rays much but I’m guessing something like this:

local partonray = workspace:FindPartOnRay(result, character)

if partonray then
    if partonray.Name == "SpecialPart" then
        partonray:Destroy()
    end
end
1 Like

The equivalent code would look something like this.

local params = RaycastParams.new()
params.FilterDescendantInstances = {part} -- a part for example
params.FilterType = Enum.RaycastFilterType.Blacklist

local hit = workspace:Raycast(origin, direction, params) -- replace those with your own origin and direction

if hit and hit.Instance then
    -- code, you might wanna check for something else, but I don't fully know what you're doing.
end

1 Like

When i do this i get the error:

Unable to cast value to Object

btw this is my origin and direction:

local origin = shootPart.Position
local direction = (position - origin).Unit * 300

Raycasting finds a part for you, creating a part to represent the ray than seeing what touches it is the reason you experience Touched errors.

If the raycast result is nil, no object was found during raycast.

@xKaihatsu has given you the correct method to solve this problem.

1 Like

I’ve tried it and this is how it looks in the end

local hitPart = Workspace:FindPartOnRay(origin, direction)
if hitPart and hitPart.Instance then
	if hitPart.Name == "SpecialPart" then
		hitPart:Destroy()
	end
end	

But this still doesn’t work and just gives an error “Unable to cast value to Object”

You do not use :FindPartORay(), it is meant to use a Ray.new object and is deprecated. You are recommended to now use :Raycast() and RaycastParams.

It should look something like this:

local raycastResult = workspace:Raycast(origin, direction, params)

To use params, you create a new one using RaycastParams.new() and set it as a variable then modify its properties to your preferences and use it as the third argument in :Raycast().

The result has properties Instance, Position, and Normal. If the result is nil, there was no instance/object found in the raycast but if there is, Instance property will tell you what object was found in the raycast.

1 Like

use an ignore list for your other lasers.

If you insist on using FindPartOnRay, try using FindPartOnRayWithWhitelist
you can utilize it to only target baseparts with

if rayhit == nil then return end -- Make sure you put this to double check that its not nil.
if rayhit:IsA("BasePart") then
-- Continue code
end

EDIT: It is still recommended to use RaycastParams()

Thanks, the problem was that i didn’t know that i should’ve used .Instance at the end :sweat_smile: Thanks for your help!