Detecting water with raycast?

Citizen.CreateThread(function()
  while true do
    Citizen.Wait(0)

    local ped = PlayerPedId()
    local headPos = GetPedBoneCoords(ped, 31086, 0.0, 0.0, 0.0)
    local offsetPos = GetOffsetFromEntityInWorldCoords(ped, 0.0, 20.0, -10.0)
    DrawLine(headPos.x, headPos.y, headPos.z, offsetPos.x, offsetPos.y, offsetPos.z, 255, 0, 0, 255)
    local rayHandle = StartShapeTestRay(headPos.x, headPos.y, headPos.z, offsetPos.x, offsetPos.y, offsetPos.z, 32, ped, 7)
    local result, hit, endCoords, surface, material, entity = GetShapeTestResultEx(rayHandle)
    print("SURFACE: " .. material)

    if hit then
      DrawMarker(28, endCoords.x, endCoords.y, endCoords.z, 0.0, 0.0, 0.0, 0.0, 180.0, 0.0, 0.2, 0.2, 0.2, 255, 128, 0, 50, false, true, 2, nil, nil, false)
    end
  end
end)

So I am trying to get the raycast to collide with water and water only…

but when it comes to the water? flag (32) it doesn’t detect anything… but if I set the flag to say 1 it detects the other surfaces just fine.

This is what my debug stuff looks like when I have the flag set to 1.

When the flag is set to 32 (the water? flag) that line just goes through the water and collides with nothing.

Does anyone know if you can get raycasts to collide with water?

1 Like

I tried for a long time to get raycasts to intersect with water but it was not successful.
The “workaround” I made to detect if a player is facing water is this (it is really specific to my use case) :

local function IsFacingWater()
	local playerPed = PlayerPedId()
	local coords = GetOffsetFromEntityInWorldCoords(playerPed, 0.0, 2.0, -1.5)
	local ped = CreatePed(29, 'mp_m_freemode_01', coords, 0.0, false, false)

	SetEntityAlpha(ped, 0, 0)
	SetEntityCollision(ped, false, true)

	Wait(1000)

	local inWater = IsEntityInWater(ped)

	DeleteEntity(ped)

	return inWater
end

I hope this will help you. If you get a raycast to detect water please tell me.

1 Like

Oh I didn’t think of doing that. Thanks that is a pretty good work around.

Thank you.

perhaps something like this rather?

http://runtime.fivem.net/doc/natives/?_0xFFA5D878809819DB

If anyone wants the code I wrote for this… I used this to find water for fishing.


function IsFacingWater()
  local ped = PlayerPedId()
  local headPos = GetPedBoneCoords(ped, 31086, 0.0, 0.0, 0.0)
  local offsetPos = GetOffsetFromEntityInWorldCoords(ped, 0.0, 50.0, -25.0)
  local hit, hitPos = TestProbeAgainstWater(headPos.x, headPos.y, headPos.z, offsetPos.x, offsetPos.y, offsetPos.z)
  return hit, hitPos
end

This function returns a boolean, vector3

I used the head position for a higher vantage point so that players could say behind pier rails and still ping water below at an angle.

Thank you @nta

8 Likes

i may be late but ive written a code that will actually hit water

	CreateThread(function()
		while true do
			Wait(0)
			local ped = PlayerPedId()
			local playerPos = GetEntityCoords(ped)
			local groundcheck = false
			local groundCheckDistance = 2.0
			local groundCheckFlags = 0
			local groundCheckIgnore = ped
			local offsetPos = GetOffsetFromEntityInWorldCoords(ped, 0.0, 20.0, -10.0)
			DrawLine(playerPos.x, playerPos.y, playerPos.z, offsetPos.x, offsetPos.y, offsetPos.z, 255, 0, 0, 255)
			local _, hit, hitPosition, surfaceNormal, material, _ = StartShapeTestRay(playerPos.x, playerPos.y, playerPos.z, playerPos.x, playerPos.y, playerPos.z - groundCheckDistance, groundCheckFlags, groundCheckIgnore)
			if hit then
	            print("Hit: " .. hitPosition)
				local _, hitGround, hitGroundPosition, hitGroundNormal, hitGroundMaterial, _ = GetShapeTestResultEx(hit)
				print("SURFACE: " .. material)
				DrawMarker(28, hitGroundPosition.x, hitGroundPosition.y, hitGroundPosition.z, 0.0, 0.0, 0.0, 0.0, 180.0, 0.0, 0.2, 0.2, 0.2, 255, 128, 0, 50, false, true, 2, nil, nil, false)
			end
		end
	end)
2 Likes