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:
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]
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)
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?
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.
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.
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
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?