Raycasting to detect terrain?

This raft is using body gyro,position,velocity to move and it is working fine.

You will get a better explanation to the problem here : https://i.gyazo.com/e1b406646d7e7ec585fa4592ef77a230.gif

So, I want to stop the force when the raft is on different surface than water

After some searching I have found raycasting could help me,but I don’t know how it can be used to detect the terrain.Help!

9 Likes

You could probably use the 4th parameter of :FindPartOnRay which is a bool detecting whether you should ignore water or not. https://developer.roblox.com/api-reference/function/Workspace/FindPartOnRay

I haven’t messed around with this, but I assume just set it to false and then you could detect if the ray doesn’t hit terrain water then you can stop the force.

6 Likes

Raycasting does indeed detect Terrain, as well as parts. When casting rays there is an argument that you can pass which will accomplish what you need.

the last argument, IgnoreWater (which is a bool value) can be used to make sure the ray isnt hitting water, since that’s not what you are looking for.

So you could cast a ray going down from the bottom of the boat, and listen for what it hits. So heres a script example:

 local objecthit, hitposition = workspace:FindPartOnRay(YourRayHere, YourRaftHere, false, true) -- last argument is true to make sure we arent listening for water
 if objecthit.Name == "Terrain" or objecthit.ClassName == "Part" then
 if (YourRayHere.Origin - hitposition).magnitude < 2 then -- checking if the terrain is close enough to the raft's hull
 --stop your raft
 end
 end

Heres another way to make your ray have a limit to how far it can detect parts, to make sure you aren’t just stopping when your ray hits the bottom of the lake, which is clearly not water.

use ray.Unit
Ray Ray.Unit [readonly].

6 Likes

I did what u said but the script is not working

https://gyazo.com/39462187ab898a908eb39d99142c658e

https://gyazo.com/19f8cb9ecbe0855e331755b030d976fa

3 Likes

I wasn’t giving you a script, I was giving you a snippet of a larger script. My purpose in responding to you wasn’t just to give you a script, because it won’t help anyone to learn. I was trying to show you a Method from which you can implement it into your own code.

2 Likes

Ik,I did but it is not working.I was checking it out in smaller scale like if it works it would print but nothing happens thats why I was asking if there is something I could fix

2 Likes

Could you make a simple test place and post it? I’d be happy to help you figure it out.

1 Like

…your part’s position wouldn’t happen to be 9 studs above the surface of the baseplate, would it?

That would be the conditions required to print absolutely nothing in the output log.

1 Like
local objecthit, hitposition,normal,material = workspace:FindPartOnRayWithWhitelist(YourRayHere, {workspace.Terrain}, false, false)
local hitwater = false
if objecthit.Name == "Terrain" and material  == Enum.Material.Water then
hitwater = true
end
--if hitvalue is false, cancel out velocity in that corners direction. Otherwise, do nothing.

I believe this might work better.

1 Like

I even tried 100 but still it does not work

1 Like

How are you constructing your rays?

1 Like

https://gyazo.com/39462187ab898a908eb39d99142c658e --Script

Also UnCopylocked Place : RaftProblem - Roblox

1 Like

I tested the place. First things first, the code is in a local script so it doesn’t run. You need to place it in a server script if you want it to run server-side.

Also I’ve found out the issue. The problem is that the position of the raft is already in the water, so it ignores the water and the next thing the ray picks up is the grass underneath. Rays have this weird thing where if the starting position is within a part, it ignores that part. To fix this is simple, set the starting position of the ray to be a little bit higher than the raft position. I changed the first line to this and it worked:

YourRayHere = Ray.new(workspace.Raft.Position + Vector3.new(0, 10, 0), Vector3.new(0,-10,0)*100)
5 Likes

You might also wanna have a ray being cast from a position in the front and one in the back so that if you accidently hit land you’re still able to go back.

3 Likes

So I edited the script and it is working fine but the problem is that now how can I repeat the script efficiently every time the raft moves to check the raft is not on Land

–script

YourRayHere = Ray.new(workspace.Raft.Model.Position + Vector3.new(0, 10, 0), Vector3.new(0,-10,0)*100)

YourRaftHere = script.Parent

local objecthit, hitposition = workspace:FindPartOnRay(YourRayHere, YourRaftHere, false, false)

if objecthit.Name == "Terrain" or objecthit.ClassName == "Part" then

if (YourRayHere.Origin - hitposition).magnitude < 10 then – checking if the terrain is close enough to the raft’s hull

print("Working")–stop raft

end

end

1 Like

You can put it in a while loop and check like every 0.5 seconds, like this:

while wait(0.5) do
-- Put all the code here
end
1 Like

I will try it :slight_smile:

2 Likes

Bad idea. I would use a RunService.Stepped loop if done on the server, or a RunService.Heartbeat loop on the client. This is not an expensive call, one ray a frame is nothing. If you have some sort of event that fires when the ship moves, use that though.

2 Likes

How is it a bad idea? I’ve done checks like this countless of times and I never had to do it every frame. The ship doesn’t move fast enough that you need to check every frame. If anything, the wait delay could be dropped lower to like 0.1 if you want more precision, but definitely not every frame.

1 Like

You can do around 60,000 raycast calls without any performance issues. There’s no reason to do it in a fixed amount of time as slow as 0.5 seconds, There can be visible time delays which makes it look horrible. Why would you not do it every frame?

1 Like