This post has out of context replies as it was initially a falsy bug report.
Right now, the page for RaycastParams does not reflect on a very important limitation of the object, which is that it cannot be altered via table.insert and table.remove.
The DevHub should be updated to reflect that the object cannot be altered with these methods, and the property must explicitly be set to a table rather than edited inline.
My general habits with Lua say to simply use table.insert inline, and when I did this, I spent a great deal of time confused as to why it wasn’t working. This could be very easily alleviated with a documentation change.
The documentation makes a false statement which threw me off as well. Highlighted in a blue box on the RaycastParams page is:
Unlike most datatypes on Roblox, all the members of RaycastParams can be changed without creating a new object. When raycasting repeatedly, you should re-use the same object.
In addition to table.insert, I tried re-assigning via RaycastParams.FilterDescendantsInstances = {inst1, inst2}
as well as RaycastParams.FilterDescendantsInstances = {unpack(table_of_instances)}
and neither of these resulted in any actual change to FilterDescendantsInstances once it had an existing value. The only method that worked for me was creating a new RaycastParams and starting over.
That statement isn’t incorrect. You can modify all the members of the RaycastParams object.
The problem that has to be described is that when you query FilterDescendantsInstances, you get a table that is a copy of what you originally put in it. It is not a pointer that lets you directly modify FilterDescendantsInstances. This would be infeasible since the representation on the engine side is different than on the Lua side. The difference with other API on FilterDescendantInstances is that they are not tables (numbers, strings, enums, etc) and so they are always passed by value rather than by reference, so you don’t see this issue occur there since you are forced to set them in RaycastParams directly.
The documentation should mention that when you query FilterDescendantsInstances, you get back a pointer to a copy of the contents of FilterDescendantsInstances. You can then modify those contents and set it back.
Interesting. When I tried to create a simple testcase I observed the behavior you described. It looks like the behavior I observed originally occurs only under certain conditions. I was able to repro it with the following test case:
Paste the below code into a LocalScript under StarterPlayerScripts
Put a breakpoint on the “table.insert” line
Single-step around the loop and observe that the error condition is hit.
local part1 = Instance.new("Part")
part1.Anchored = true
part1.CanCollide = false
part1.Parent = workspace
local part2 = Instance.new("Part")
part2.Anchored = true
part2.CanCollide = false
part2.Parent = workspace
local params = RaycastParams.new()
params.CollisionGroup = "Test"
params.FilterType = Enum.RaycastFilterType.Blacklist
local function OnRenderStepped(step)
local ignoreList = {part1}
while true do
params.FilterDescendantsInstances = {unpack(ignoreList)}
print(#params.FilterDescendantsInstances)
if #params.FilterDescendantsInstances ~= #ignoreList then
error(string.format("expected %d entries, got %d", #ignoreList, #params.FilterDescendantsInstances))
end
local res = workspace:Raycast(Vector3.new(0,0,-5), Vector3.new(0,0,5), params)
if res then
table.insert(ignoreList, res.Instance)
else
break
end
end
end
game:GetService("RunService").RenderStepped:Connect(OnRenderStepped)
Interestingly, if I add a guard variable to prevent re-entrancy on the above routine, the problem does not manifest. Perhaps the Raycast() routine can run concurrently with other code on the client and temporarily locks the FilterDescendantsInstances table while it is in progress.
Yikes, something is going terribly wrong here, you’re certainly right about that!
However, it isn’t an issue with the RaycastParams, the RaycastParams is dutifully storing and returning the values that are getting passed to it, rather the script debugger is somehow passing garbage into the RaycastParams when single stepping.