Ignore certain parts in Raycasting?

Do you use FindPartOnRayWithIgnoreList?

1 Like

Yes :upside_down_face: :upside_down_face:

1 Like

Try to get close to an ignore part that was included in the table like I did in the gif, did that happen? If not, can you try to provide a gif? Thanks.

3 Likes

there
https://gyazo.com/00cbd6c2f7ccd96edfe7db1b6c713436
Red is in folder
Blue isn’t

image

1 Like

Can you demonstrate it like mine? Get as close as you can to the brick.

1 Like

https://gyazo.com/03d74f5a0567076e625a1252aba44e8b

I have no idea why this happens.

2 Likes

It doesn’t look like you got any solution to this last problem when you got close to the red brick, this is because of the way angles are calculated.
The red brick may be ignored by the ray, but it’s not ignored by the mouse. Sorry if you found a solution for this prior, but this is my take on it.

2 Likes

You’re right, I tried to put all characters inside a Model and link Mouse.TargetFilter to it, but sometimes when your mouse is pointed directly to the character, the ray will completely ignore the character and go straight behind (maybe next to the character)

Currently I found a solution, I give up on using Mouse.TargetFilter. I put all the ignoring parts inside a table, then link it with FindFirstRayWithIgnoreList. I also start casting the ray from the character’s torso instead of the ShootingPart, but keeping all visual effect from the ShootPart, this is an ultimate solution because it can also prevent from shooting through walls, so far I don’t encounter any problems that I mentioned above.

1 Like

An easy way to fix the issue with weird angles (as OP @Headstackk and @Sunx_x showcased) is to use Mouse.UnitRay, which casts a ray that originates from the CurrentCamera. You would have to construct another Ray using Mouse.UnitRay’s properties (Ray.Direction, Ray.Origin) for the distance though, as it’s a unit ray

You can also use Camera::ScreenPointToRay which you also have to re-construct the ray (since both Mouse.UnitRay and Camera::ScreenPointToRay are both unit rays)

Using the property / function I mentioned above, I was able to make this: https://gyazo.com/1ced7a2ef20441f7c8fc782ac4f0e13e

2 Likes

This is almost certainly the best way to do it. Sure you can mess around with collection service and what not, but if you’re dumping a gigantic array of parts in the FindPartOnWayWithIgnoreList function it’s not going to be more efficient, so why go through all that trouble?

Here’s a basic one, I think it actually started life in the Roblox jeep some years back. It has a re-entry limit so it wont crash if by some weird bug it ends up in an infinite loop, or if you point it at a clump of thousands of parts or something. It’s currently set to ignore bricks with can collide off or with a transparency higher than 0.9, but you can set it to ignore whatever you want by changing
collide = (hit.CanCollide and hit.Transparency < 0.9)

function module.new(startPosition, offset, ignoreList)
    if not ignoreList then ignoreList = {} end
	local reEntry = 0
	local maxDistance = offset.magnitude
	local direction = offset.unit
	local lastPosition = startPosition
	local distance = 0
	local ignore = ignoreList
	local hit, position, normal, material
	local collide
	
	repeat
		reEntry = reEntry + 1
		local ray = Ray.New(lastPosition, direction * (maxDistance - distance))
		hit, position, normal, material = workspace:FindPartOnRayWithIgnoreList(ray, ignore, false, true)
		if hit then
			collide = (hit.CanCollide and hit.Transparency < 0.9)
			if not collide then
				table.insert(ignore, hit)
			end
		end
		distance = (startPosition - position).magnitude
		lastPosition = position
	until distance >= maxDistance or collide or reEntry > 10
	
	if reEntry > 10 then 
		warn("Raycast reentry limit exceeded! Ray from: ", startPosition, "Heading:", offset)
	end
	
	return hit, position, normal, material
end

Since it also has an ignore list as an optional parameter, you could also use it with collection service, so you don’t have to manually tag every single cancollide off part that ever gets created in your game but you can still tag parts to be ignored that are cancollide and not transparent if you ever need to do so.
You can then also use this in place of Mouse.Hit so that you don’t end up with the gun problem shown a few posts above when near parts you can shoot thorugh. (Especially if your map uses large invisible parts!) When the player clicks, just use the following code

local RaycastModule = require(The Above Module)

local DISTANCE = 200 --How far the players click will travel to find a target before stopping

function GetMouseHit()
   local Hit, Position =  RaycastModule.new(Mouse.UnitRay.Origin, Mouse.UnitRay.Direction * DISTANCE)
  return Hit, Position
end

Or a similar method using Auhrii’s module instead.

13 Likes

For me personally, first I have a table of things I want to ignore by default.
Then I make a propetries table for things i want to get in the raycast.

local function FilteredRaycast(ray, propertyFilterTable, IgnoreList)
    if not IgnoreList then IgnoreList = {} end
    local part
    repeat
        local p = workspace:FindPartOnRayWithIgnoreList(ray, IgnoreList)
        if p then
            local IsFiltered = true
            for k,v in pairs(propertyFilterTable) do
                if p[k] ~= v then
                    IsFiltered = false
                end
            end
            if IsFiltered then 
                part = p
            else
                table.insert(IgnoreList, p)
            end
        else
            break -- Ray failed to hit anything
        end
    until part
    return part
end

local p = FilteredRaycast(Ray.new(), {CanCollide = true})

-- Please note that I just wrote this on the forum and this script is untested,
-- This is just an example of what I usually do

I kept hitting tab trying to indent code and ended up saving edits before I was done, I apologize for the many edits

1 Like

Untested, but is it really a good way?

  1. Create collision groups

CollisionGroup

  1. Set the raycast into Collision group

    raycastParams.CollisionGroup = 'Raycast'

  2. Set the anti raycast parts into Collision group

local physicsService = game:GetService('PhysicsService')

for _, part in pairs(workspace:GetDescendants()) do
	if part:IsA('Accessory') then
		physicsService:SetPartCollisionGroup(part.Handle, 'AntiRaycast')
		print(part)
	end
end
6 Likes

was this ever solved? becuase there might be other people looking for the same solution. (im not looking for a solution cuase i’ve got my own)

I’d do a raycast with a whitelist or blacklist which ever is smaller

This will most of the time work with the new raycast

I know this post Is old, but if you encounter this issue, you could either create a folder and put all the parts (might also be recommended to turn off CanQuery) that you want to be ignored In there or create a script that turns off CanQuery for your character’s hats whenever the character spawns

--[[
Creates a loop to check if any new hats were added.
You can use ChildAdded instead, but I prefer this loop.
]]

while wait() do

local d = script.Parent:GetChildren() 
for i=1, #d do 
	if (d[i].className == "Accessory") or (d[i].className == "Hat") then 
		d[i].Handle.CanQuery = false
			
	--LAYERED CLOTHING REMOVAL--
			
	--[[elseif (d[i]:FindFirstChild("Handle")) and (d[i].Handle:FindFirstChildOfClass("WrapLayer")) then
		d[i]:Destroy()]]
		
	  end 
   end
end
1 Like

try adding workspace:GetDescedants above descedantadded and do the same check as descedant added. dont delete the descedant added check because it is needed to work too.