Generalizing Whitelists/Blacklists for huge API performance gains

I was replying to @Davidii’s raycasting use-case thread, and had an idea for unifying everything related to whitelists, blacklists, and the much needed raycast-with-callback feature.

I’m suggesting a generalized ‘InstanceCondition’ object for whitelisting/blacklisting things. This would generalize blacklists, whitelists, and callbacks, plus some specific use-cases like testing for transparency/non-cancollide/class could have their own types to boost performance


InstanceCondition could be an abstract class of sorts

bool instanceCondition:TestInstance(instance)

Some new methods where InstanceConditions could be used, and what methods it improves upon.

  • workspace:FindPartOnRayWithCondition( Ray ray, InstanceCondition condition )
  • workspace:FindPartOnRayWithIgnoreList().
  • workspace:FindPartOnRayWithWhitelist()
  • instance:FindFirstChildOfCondition( InstanceCondition condition )
  • instance:FindFirstChildOfClass()
  • instance:FindFirstChild()
  • instance:GetChildrenOfCondition( InstanceCondition condition )
  • instance:GetChildren()

These all have huge performance implications when doing large searches and checks.

InstanceCondition Types

Whitelist — Returns true if the instance is in the list, or a descendant of an instance in the list.

InstanceCondition.newWhitelist({instance1, instance2, ...})

Callback — Passes the instance to a Lua function. There could be an option to make this cache results to reduce duplicate instance calls and boost performance.

InstanceCondition.newCallback(function(instance)
	return instance.CanCollide and instance.Transparency < 1
end)

PropertyEquals — Returns true if the property is equal to a value

InstanceCondition.newPropertyEquals("Transparency", 0)
-- Alternative using Callback:
InstanceCondition.newCallback(function(instance)
	return instance.Transparency == 0
end)

IsA — Returns true if instance:IsA(className)

InstanceCondition.newIsA("BasePart")
-- Alternative using Callback:
InstanceCondition.newCallback(function(instance)
	return instance:IsA("BasePart")
end)

Not — Applies ‘not’ to the given condition. It would turn blacklists into whitelists, and whitelists into blacklists.

InstanceCondition.newNot(instanceCondition)
-- Blacklists could have their own type, or be implemented using:
InstanceCondition.newNot(InstanceCondition.newWhitelist({instance1, instance2, ...}))

And — Returns true if every condition is met

InstanceCondition.newAnd({condition1, condition2, ...})

Or — Returns true if any condition is met

InstanceCondition.newOr({condition1, condition2, ...})

There might need to be special types for testing raycast collisions with terrain, and this might seem like a complicated solution to a simple problem, but this would simplify a lot of the API moving forward.

39 Likes

Maybe this could also be used for filtering instances in the studio explorer :open_mouth:

1 Like

This would be useful with collision layers as well!

This really needs to be a thing.

Imagine having this applied to instance:GetDescendants(), this has so many use cases! :open_mouth:

For example instead of calling GetChildren and IsA thousands of times using something like this:

local function recurse(container)
	local children = container:GetChildren()
	for i = 1, #children do
		local child = children[i]
		if child:IsA("BasePart") then
			child.Locked = true
		end
		recurse(child)
	end
end
recurse(workspace)

You could just do this:

local parts = workspace:GetDescendantsOfCondition(InstanceCondition.newIsA("BasePart"))
for i = 1, #parts do
	parts[i].Locked = true
end
4 Likes