Using raycasts to detect terrain is not work

Hello everyone, I am working on a placement system that allows you to place objects, but I don’t want player to place objects on lakes. To do this, I tried to use raycasts…

local ray = Ray.new(CraftingTable.PartMain.Position,CraftingTable.PartMain.CFrame:vectorToWorldSpace(Vector3.new(0, -6, 0)))
	local hit, position, normal, material = workspace:FindPartOnRay(ray,CraftingTable.CraftingTable)
	print(position)
	if material == Enum.Material.Water then
		game.ReplicatedStorage.FireWarning:FireClient(Player,"Too close to water! place it on a bridge instead.")
	end

However, it doesn’t work. This is my first time using raycasts so I am quite confused, any help would be appreciated.

Try

print(position)
print(material)

to see what the ray is hitting.

How high is CraftingTable.PartMain.Position? If it’s over 6 studs high then your ray isn’t going to hit the Terrain.

You could try putting a breakpoint in your code to step through it line by line and see what the variables are at each step.

Also the FindPartOnRay function is deprecated (but does still work fine, so that’s not really your issue), you may have more success with the Raycast method instead.

1 Like

i don’t think its required to use the vectorToWorldSpace normalization method, the issue being that the CraftingTable may be actually facing down though texture might be at a different rotation that is not facing the ground

Wait, I’m not too sure about how this works, but aren’t you calling CraftingTable.CraftingTable? Is the Part named CraftingTable inside a Model named CraftingTable?
local hit, position, normal, material = workspace:FindPartOnRay(ray,CraftingTable.CraftingTable)

Sorry, I had to do something. I think I may have found the problem, which is that the ray hits another part of the craftingtable (it printed enum.material.wood)…
Is there a way to stop certain part from getting detected by the ray?

This is the hierarchy:
image

Just like @nicemike40 said FindPartOnRay is deprecated. Use workspace:Raycast for a more accurate raycast. workspace:Raycast should also fix your issue with raycasts not detecting terrain. If your also firing a raycast from the player character position create a raycast blacklist that blocks off the limbs because that may be what the ray is picking up

Look up ray whitelist and blacklist.
Also, if you are searching for this in Workspace as a tool won’t it be put in a Player?

Use workspace:Raycast() instead as the older method is deprecated as the new ray cast method gives you more results. workspace:Raycast() takes an origin and a direction (normal vector) and raycast params.

New ray cast method:
https://developer.roblox.com/en-us/api-reference/function/WorldRoot/Raycast

As for the ray casting, the ray cast function returns a ray cast result object which has various properties.

result object has a property your looking for. result.Material, this property works on terrain and parts. Use the Enum.Material to compare materials with the result.

Ray cast result object page:
https://developer.roblox.com/en-us/api-reference/datatype/RaycastResult

1 Like

I changed my script to the following, following Cerberus’s advice

	local params = RaycastParams.new()
	params.IgnoreWater = false
	params.FilterDescendantsInstances = {CraftingTable.CraftingTable}
	params.FilterType = Enum.RaycastFilterType.Blacklist
	
	local hit, position, normal, material = workspace:Raycast(CraftingTable.PartMain.Position,Vector3.new(0,-6,0))
	
	print(position)
	print(material)

However, now, the last two lines print nil.
edit: print(hit) returns RaycastResult{PartMain @ -41.0951691, 3.15759182, 173.189194; normal = 0.000505845994, -0.999999464, -0.000973608519; material = Wood}

Turns out I just wasn’t using Raycast correctly

2 Likes