Hello! I am trying to make a raycasting script that will exclude every descendant of workspace, as long as it is outside of my Map folder, its ancestor doesn’t have a Humanoid, CanCollide is off and transparency is equal to or greater than 0.5.
However, even though there is a character in the way of the mouse position, the raycast result doesn’t stop on the character, but rather goes through it.
local function getMousePosition()
local mouse = plr:GetMouse()
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
local exclude = {}
for _, child in plr.Character:GetChildren() do
if child:IsA("BasePart") then
table.insert(exclude, child)
end
end
for _, descendant in workspace:GetDescendants() do
if descendant:IsA("BasePart") then
if not table.find(exclude, descendant) then
local isPartOfMap = descendant:IsDescendantOf(workspace.Map)
local modelAncestor = descendant:FindFirstAncestorWhichIsA("Model")
local hasHumanoidAncestor = modelAncestor and modelAncestor:FindFirstChildOfClass("Humanoid")
if not isPartOfMap and not hasHumanoidAncestor then
table.insert(exclude, descendant)
end
if not descendant.CanCollide and descendant.Transparency >= 0.5 then
table.insert(exclude, descendant)
end
end
end
end
params.FilterDescendantsInstances = exclude
local result = workspace:Raycast(tool.Handle.Position, (mouse.Hit.Position - plr.Character.HumanoidRootPart.Position).Unit * math.huge, params)
print(result)
if result then
return result.Position
else
return mouse.Hit.Position
end
end
here you are adding the character parts to the exclude table so they are being ignored by the raycast. Would it work to instead set the filter type to include and set the FilterDescendantsInstances to {workspace.Map, character1, character2, …}?
Edit: unless you are only excluding the local character and the character not being detect is another character
local k_maxRaycastDistance = 15000 -- This is the max raycast distance that can be calculated!
local k_transparencyCutoff = 0.5 -- This is how transparent an object has to be to be seen by the mouse
local function getMousePosition()
local localPlayer = game.Players.LocalPlayer
local mouse = localPlayer:GetMouse()
local excludeArray = {} -- This is our final list of excluded parts
local excludeLookup = {} -- This is a look up table so we can check if we've already excluded parts
local characterPartLookup = {} -- This is a lookup table so we can check if a part is in a humanoid
-- Look up tables are nice because they have a constant look up time! table.find() will take longer if there's more stuff in the table,
-- but checking if the key is in the table takes the same amout of time no matter how big the table is!
local function canBeExcluded(instance : Instance)
return instance:IsA("BasePart") and not excludeLookup[instance] and not characterPartLookup[instance]
end
local function excludePart(part : BasePart)
excludeLookup[part] = true
table.insert(excludeArray, part)
end
-- First go through and find all the characters! We don't want to add any of their parts
-- We can do this by find all the humanoids in our workspace and removeing their parents children from the possible parts
for _, descendant in game.Workspace:GetDescendants() do
if descendant:IsA("Humanoid") and descendant.Parent ~= localPlayer.Character then
for _, humanoidInstance in descendant.Parent:GetDescendants() do
characterPartLookup[humanoidInstance] = true
end
end
end
-- Now lets go through and exclude parts
for _, descendant in game.Workspace:GetDescendants() do
if canBeExcluded(descendant) then
local isPartOfMap = descendant:IsDescendantOf(game.Workspace.Map)
local isNoninteractable = not descendant.CanCollide and descendant.Transparency >= k_transparencyCutoff
if not isPartOfMap or isNoninteractable then
excludePart(descendant)
end
end
end
local raycastParameters = RaycastParams.new()
raycastParameters.FilterType = Enum.RaycastFilterType.Exclude
raycastParameters.FilterDescendantsInstances = excludeArray
-- You could also change this to something like game.Workspace.CurrentCamera.CFrame.Position
-- if you wanted to get anything that was visible to the camera rather than to the tool
local origin = tool.Handle.Position
local target = mouse.Hit.Position
local directionVector = (target - origin).Unit * k_maxRaycastDistance
local result = workspace:Raycast(origin, directionVector, raycastParameters)
if result then
return result.Position
else
return mouse.Hit.Position
end
end
I suspect there a couple of issues:
your character probably had some hats or some parts that weren’t a direct child of your character model!
so you could also try switching for _, child in plr.Character:GetChildren() do
to for _, child in plr.Character:GetDescendants() do
local hasHumanoidAncestor = modelAncestor and modelAncestor:FindFirstChildOfClass("Humanoid") won’t work if the part your checking is nested inside your character model! (Like a part that’s a child of a hat instance rather than the character itself). This ones a little more tricky to solve, but the solution I provided got around it by doing a pre pass to find instances that belonged to characters!
The solution I provided will also be a little more efficient because it doesn’t use table.find (Even though it does go through the workspace twice!)