Raycasting Whitelist

With raycasting, you can currently add a blacklist (instances to be ignored), but you can’t whitelist items. A whitelist would allow us to essentially say “ONLY look at these objects when casting the ray”. When doing special operations with raycasting, having this ability would be really nice. For instance, if I am trying to determine points on a single model and don’t want other 3D objects around the model to interfere.

This can definitely be done by constructing a blacklist of every instance parent except for the items you want whitelisted, but it would be nice to just have a method to do this by default.

To go along with the absurdly-long naming practices, my recommendation:

workspace:FindPartOnRayWithWhiteList(ray, whitelistTable, ...) 

Edit: For those who are interested, here’s a way to create a static ignore list from a whitelist table. Perhaps there’s a better way, but just wrote it up pretty quickly and tested it out to make sure it worked:

[details=Click to show sourcecode][code]
– Creates an ‘ignore’ table for FindPartOnRayWithIgnoreList
function IgnoreListFromWhiteList(whitelist)
local ignoreList = {}
local whitelistDict = {}
local function IsAncestorOfWhitelist(parent)
for _,v in pairs(whitelist) do
if (parent:IsAncestorOf(v)) then
return true
end
end
return false
end
local function Scan(parent)
for _,v in pairs(parent:GetChildren()) do
if (IsAncestorOfWhitelist(v)) then
Scan(v)
elseif (not whitelistDict[v]) then
ignoreList[#ignoreList + 1] = v
end
end
end
for _,instance in pairs(whitelist) do
whitelistDict[instance] = true
end
Scan(game.Workspace)
return ignoreList
end

– Construct an ignore list from a whitelist:
local ignore = IgnoreListFromWhiteList {
– Whitelist:
game.Workspace.BasePlate;
game.Workspace.SomeModel.Test;
}
[/code][/details]

64 Likes

image.jpeg

11 Likes

I once wrote a working CreateWhitelist like you did here, but never actually used it.
One of those “I script it because I can, not because I need it”.
Having a built-in method would be handy (and more efficient, especially when you have 10k parts)

This would be useful for my hover racers so they only stick to the race track and not other cars or invisible objects like checkpoints.

Could we get this for Region3s too?

7 Likes

Yes please! I need this so much, I use raycasting for everything.

1 Like

Thanks for all the support of this idea. I’m surprised people care this much about it.

Manytimes this would help alot, AND improve preformance aswell…

1 Like

I’m gonna necro this thread and ask if this is somewhere in the pipeline… or if not, could we hope for it somewhere in the near (soon™) future?

EDIT: I don’t which admin to tag… Can someone who knows tag them please?

2 Likes

Asked about this at RDC last week and @zeuxcg told me to make a post about it on this forum, but since this topic already exists I’ll just bump this instead. As far as I know @Silent137 regularly checks the Feature Requests section to add things to the Gameplay & Studio Features Trello board but I couldn’t find this feature on the board, so… can another look be given at this? :wink:

4 Likes

Silent handles Studio features. @spotco manages the client portion of the board.

2 Likes

Can this be implemented in lua?
Does anyone have an implementation in lua, and do you use it in a live game?

The OP contains a code block which ‘inverts’ a whitelist to an ignorelist at the end, so yes. The code however is quite complex for beginning developers. It also doesn’t look that efficient, especially for games with a high instance count. I my opinion developers shouldn’t need to recursively loop through the whole game hierarchy to invert a whitelist to an ignorelist.

1 Like

Sure, we can take a look.

However, does anyone actively use a lua version of this?
Performance should not be the primary motivation behind adding a new API, especially if it can be done in a small amount of lua. Performance can always be improved with techniques (splitting the operation across frames, etc).
In addition, if you’re using a whitelist then your total number of parts is likely to be small so performance doesn’t seem like it should be a big deal for this.

For projectile penetration, the only way to find the exit point from a hit part is to go completely through the part, then do a 180 and raycast back through the part from the other side. What if there’s another part in the way though? Now I have to add my whole level to the ignore list, or set up raycasting that continually resumes itself and adds the hit to the ignore list when it hits a part not in the custom whitelist.

If you have to whitelist the whole level, couldn’t you just use the blacklist for the second raycast? (Not 100% understanding why you’re doing what you’re doing, but the performance characteristics seem fine)

Yes, and the third, and the fourth, and the fifth, etc. Performance benefit is not the only reason whitelisting is useful. If the only thing I care about are a particular assortment of parts, a whitelist allows me to observe only those, saving me from the trouble of repeatedly telling ROBLOX “Sorry, try again” every time it runs into a part I already knew I didn’t want to be taken into account from the beginning.

1 Like

@BouyertheDestroyer has volunteered to do look into it

5 Likes

Til then, here’s something that should be more performant than the code in the OP

local RaycastWhitelist do
	local FindPartOnRay = workspace.FindPartOnRay
	local GetChildren = game.GetChildren
	local ray = Ray.new

	local function GetDescendants(root)
		local t, tn, stack = {}, 1, GetChildren(root)
		local ptr = #stack
		local obj = stack[ptr]
		t[tn] = obj

		while obj do
			tn = tn + 1
			stack[ptr], ptr = nil, ptr - 1
			local des = GetChildren(obj)
			local k = #des
			for i = 1, k do
				stack[ptr + i] = des[i]
			end
			ptr = ptr + k
			obj = stack[ptr]
			t[tn] = obj
		end
		
		return t
	end

	function RaycastWhitelist(r, whitelist, ignoreWater)
		local w, dir, last = {}, r.Direction, nil

		for i = 1, #whitelist do
			local item = whitelist[i]
			w[item] = true
			local descendants = GetDescendants(item)
			for i = 1, #descendants do
				w[descendants[i]] = true
			end
		end

		while true do
			local part, hit, norm, mat = FindPartOnRay(workspace, r, last, false, ignoreWater)
			if not part or w[part] then
				return part, hit, norm, mat
			else
				last = part
				r = ray(hit, dir)
			end
		end
	end
end

@people in the discussion

When you think of a method like this, would you expect it to work like FindPartsOnRayWithIgnoreList, which includes terrain and has parameters like ignoreWater and terrainCellsAreCubes, and has limits distance, or do you think of something that would only be used for part geometry and check to see if it ever collides with whitelisted objects?