I was wondering if it was possible to make GetPartsBoundsInBox or a raycast have a whitelist with a specific terrain or material. Thanks.
I’m pretty sure you can achieve a similar result if you raycast recursively. You raycast once, check what is hit, and if the .Instance
doesn’t qualify you keep repeating the raycast at the new hit location until you got what you wanted or until you’ve exhausted the length budget.
Here’s an example below, I whitelisted the Mud and Basalt material. The raycast will pass through anything that aren’t of those materials
local function RaycastForMaterial(origin: Vector3, direction: Vector3, whitelist: {[Enum.Material]: true}): RaycastResult?
local inset: Vector3 = direction.Unit*.01 --offset the next raycast origin inwards a bit
while true do
local rcr: RaycastResult? = workspace:Raycast(origin, direction)
if rcr then
if whitelist[rcr.Material] then
return rcr
end
local travelled: Vector3 = rcr.Position - origin
origin = rcr.Position+inset
direction -= travelled
continue
end
return
end
end
local uis = game:GetService('UserInputService')
uis.InputBegan:Connect(function(k, gp)
if gp then return end
if k.UserInputType == Enum.UserInputType.MouseButton1 then
local mPos: Vector2 = uis:GetMouseLocation()
local mRay: Ray = workspace.CurrentCamera:ViewportPointToRay(mPos.X, mPos.Y)
print(RaycastForMaterial(mRay.Origin, mRay.Direction*1e3, {
[Enum.Material.Basalt] = true,
[Enum.Material.Mud] = true,
}))
end
end)
I actually have a similar function for making raycasts ignore players that I can recycle for this purpose.
Is it possible to have a whitelist and a blacklist in a raycast? I was thinking I can reduce the amount of raycasting that has to be done by whitelisting Workspace.Terrain but then I cant blacklist parts that the raycast comes across that aren’t water.
It should be fairly easy to modify the function I provided to use a proper RaycastParams, and just have that be an additional filter that whitelist/blacklist based on the hierarchy.
If you’re talking about blacklisting materials instead, you can add a boolean parameter to specify that and reuse the whitelist
parameter like this:
if (isBlacklist and not whitelist[rcr.Material]) or whitelist[rcr.Material] then
return rcr
end
Not blacklisting materials but blacklisting the actual terrain it goes through (I use the word terrain since parts will be excluded if I have a strictly terrain whitelist. I am basically trying to detect only water with raycasts.) I want to add the terrain it goes through that isnt water to a blacklist before raycasting again.
alternatively is there a way I can reference terrain in a script? E.g getting all the terrain in the game and if the material is water then i add it to the whitelist? If I could do that I’d only ever need to raycast once.
Then all you need to do is whitelist water and nothing else. The function I gave will pass through anything that isn’t whitelisted, meaning that it will continue to raycast through terrain until it hits water.
Here’s the edited function that also takes in a RaycastParams to whitelist terrain, and then only cast for water
local function RaycastForMaterial(origin: Vector3, direction: Vector3, params: RaycastParams?, whitelist: {[Enum.Material]: true}): RaycastResult?
local inset: Vector3 = direction.Unit*.01 --offset the next raycast origin inwards a bit
while true do
local rcr: RaycastResult? = workspace:Raycast(origin, direction, params)
if rcr then
if whitelist[rcr.Material] then
return rcr
end
local travelled: Vector3 = rcr.Position - origin
origin = rcr.Position+inset
direction -= travelled
continue
end
return
end
end
local RCP: RaycastParams = RaycastParams.new()
RCP.FilterDescendantsInstances = {workspace.Terrain}
RCP.FilterType = Enum.RaycastFilterType.Include
local uis = game:GetService('UserInputService')
uis.InputBegan:Connect(function(k, gp)
if gp then return end
if k.UserInputType == Enum.UserInputType.MouseButton1 then
local mPos: Vector2 = uis:GetMouseLocation()
local mRay: Ray = workspace.CurrentCamera:ViewportPointToRay(mPos.X, mPos.Y)
print(RaycastForMaterial(mRay.Origin, mRay.Direction*1e3, RCP, {
[Enum.Material.Water] = true,
}))
end
end)
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.