I’m trying to shoot a ray into the ground from above and detect if it hits terrain only and not a part.
I’ve looked all over and haven’t seemed to find a solution to this yet.
if raycastResult then
if raycastResult.Instance:IsA("Terrain") then
print("terrain")
end
doesn’t seem to print anything now, here is my full script.
local rayOrigin = Vector3.new(math.random(-part.Size.X/2, part.Size.X/2) , part.Position.Y + part.Size.Y , math.random(-part.Size.Z/2, part.Size.Z/2))
local rayDirection = Vector3.new(0,-part.Size.Y,0)
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Include
raycastParams.FilterDescendantsInstances = {workspace.Terrain}
--raycastParams.RespectCanCollide = false
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
if raycastResult then
print(raycastResult)
if not table.find(blacklist, raycastResult.Material) then --not blacklisted material
print("terrain", raycastResult.Material)
local p = Instance.new("Part",workspace)
p.Position = raycastResult.Position
p.Anchored = true
end
end
I think it’s because I’m firing the ray inside a large part, so it detects that part and returns no result because it isn’t on the filterlist. How could I make this part be ignored?
The code snippet you provided seems to be on the right track. Here’s an example of how you could use raycasting to detect if a ray hits terrain and not a part:
local origin = Vector3.new(0, 100, 0) -- replace this with the starting position of the ray
local direction = Vector3.new(0, -1, 0) -- replace this with the direction of the ray
local ray = Ray.new(origin, direction * 1000) -- create a ray with a length of 1000
local workspace = game:GetService("Workspace")
local terrain = workspace.Terrain
local result = workspace:FindPartOnRay(ray)
if result then
if result:IsA("Terrain") then
print("Hit terrain")
else
print("Hit part")
end
else
print("Did not hit anything")
end
This code creates a ray starting at origin and pointing in the direction specified. It then uses the FindPartOnRay function to cast the ray and find the first object it hits. After casting the ray, we check if it hit anything by checking if result is not nil. If it did hit something, we check if it hit terrain by calling the IsA function on result and passing in "Terrain" as an argument.
I hope this helps you detect if a ray hits terrain and not a part!
local blacklist = {
Enum.Material.Air;
Enum.Material.Water;
}
local function RandomSpawnLocation(zone)
if Zones[zone]:FindFirstChild("AI") then
local part = Zones[zone]:FindFirstChild("AI")
local position = nil
repeat
local rayOrigin = Vector3.new(math.random(-part.Size.X/2, part.Size.X/2) , part.Position.Y + part.Size.Y , math.random(-part.Size.Z/2, part.Size.Z/2))
local rayDirection = Vector3.new(0,-part.Size.Y,0)
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Include
raycastParams.FilterDescendantsInstances = {workspace.Terrain}
--raycastParams.RespectCanCollide = false
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
print(raycastResult)
if raycastResult then
print(raycastResult)
if not table.find(blacklist, raycastResult.Material) then --not blacklisted material
print("terrain", raycastResult.Material)
local p = Instance.new("Part",workspace)
p.Position = raycastResult.Position
p.Anchored = true
end
end
wait(.1)
until position
end
end
Using the include option will only have the filtered instance and descendants as possible results, so it’s not the fact you’re raycasting from within a part.
Your origin is a random offset based on a parts X and Z size, and it raycasts down by the Y Size of the part. So where is this part in workspace in relation to the terrain?
Because if the Y Size is really small, the ray will naturally be small as well in this case. Make sure the part’s Y Position is at least part.Size.Y distance above the terrain (Minus a buffer for consistency), Or set the direction of the raycast to Vector3.new(0, SomeLargerNumber, 0).
Well it shoots a ray in a random x/z location inside a large part inside of my map, the y coordinate is at the very top of that part, and shoots downward. I’m trying to have it do an event when it hits terrain, I tested it to make parts spawn where it hits, and they seem to spawn on the part itself in random air, and all over the place below, but none on terrain. Not sure how to fix this
local blacklist = {
Enum.Material.Air;
Enum.Material.Water;
}
local function RandomSpawnLocation(zone)
if Zones[zone]:FindFirstChild("AI") then
local part = Zones[zone]:FindFirstChild("AI")
local position = nil
repeat
local rayOrigin = Vector3.new(math.random(-part.Size.X/2, part.Size.X/2) , part.Position.Y + part.Size.Y , math.random(-part.Size.Z/2, part.Size.Z/2))
local rayDirection = Vector3.new(0,-part.Size.Y,0)
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Include
raycastParams.FilterDescendantsInstances = {workspace.Terrain}
--raycastParams.RespectCanCollide = false
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
print(raycastResult)
if raycastResult then
print(raycastResult)
if not table.find(blacklist, raycastResult.Material) then --not blacklisted material
print("terrain", raycastResult.Material)
--local p = Instance.new("Part",workspace)
--p.Position = raycastResult.Position
--p.Anchored = true
end
end
wait(.1)
until position
end
end
Have you tried multiplying the rayDirection? Dont forget that raycast are finite on both ends, so I always recommend in cases like your’s, especially if you’re using part’s size as a basically “lenght”, to make the ray longer. Try doing:
local raycastResult = workspace:Raycast(rayOrigin, rayDirection.Unit*10, raycastParams)
It is just printing nil repeatedly from print(raycastresult)
local rayOrigin = Vector3.new(math.random(-part.Size.X/2, part.Size.X/2) , part.Position.Y + part.Size.Y , math.random(-part.Size.Z/2, part.Size.Z/2))
local rayDirection = Vector3.new(0,-part.Size.Y,0)
local raycastParams = RaycastParams.new()
--raycastParams.FilterType = Enum.RaycastFilterType.Include
raycastParams.FilterDescendantsInstances = {workspace.Terrain}
--raycastParams.RespectCanCollide = false
local raycastResult = workspace:Raycast(rayOrigin, rayDirection.Unit * 10, raycastParams)
print(raycastResult)
if raycastResult then
print(raycastResult)
if not table.find(blacklist, raycastResult.Material) then --not blacklisted material
print("terrain", raycastResult.Material)
local p = Instance.new("Part",workspace)
p.Position = raycastResult.Position
p.Anchored = true
end
end
wait(.1)
why did you comment out this line? The default filterType is blacklist, so if you just ran the script as you provided now, it ignored the terrain cells. Please uncomment this line and try it again
I tried moving it yesterday to serverstorage to make sure the ray wasnt just hitting the part, so the result i’ve been getting has been with this part in serverstorage not in workspace.
Noticed this for when you set the ray origin, make it + part.Size.Y * .5. It’s raycasting from above the part in the first place. And not the top of the part.