Is there a native function or a method to get the entity the player is looking at?

I’m trying to find a function that returns the entity the player is looking at. The only thing I found were methods tryggered by aiming at entity but no looking. If you know how to do it please write an answer

Hey there,

it’s not a single native but you can do it using a bit of trigonometry / vector calculations. Dunno if a few of the things I do can be done using a native but I know my method works :smiley:

Let’s look at it from the end:
You want to hit a ped, so for this you need the native StartShapeTestRay() together with GetShapeTestResult(). If you choose the parameters of the function correctly the result will look like this:

function GetPedInDirection(coordFrom, coordTo)
	local rayHandle = StartShapeTestRay(coordFrom.x, coordFrom.y, coordFrom.z, coordTo.x, coordTo.y, coordTo.z, 4, GetPlayerPed(-1), 0)
	local _,flag_PedHit,PedCoords,_,PedHit = GetShapeTestResult(rayHandle)
	return flag_PedHit, PedCoords, PedHit
end

This will return a ped that is positioned in a straight line between point A (named coordFrom) and point B (named coordTo) while excluding the player ped.
Now we will need to position the line such that the gameplay camera is the starting point, the direction the camera is looking to is the end point.

The starting point is easy: Use the native GetGameplayCamCoord(), which will give you the camera’s position.
So how does a line look like which starts from the camera position and goes straight where the player is looking? Answer is simple: It’s basically your crosshair, a single point on your screen.
The issue is: We’ll need to find a second point at a given distance to use in the function GetPedInDirection() as we can’t just input camera directions.

Now this is where a few natives come into play:
GetGameplayCamRelativeHeading() gives the heading of the camera relative to the player ped
GetEntityHeading() will give us the heading of the player ped
GetGameplayCamRelativePitch() gives the pitch relative to the player ped.

Thankfully the pitch of our character is 0 for basically everything (a few exceptions, e.g. being ragdolled), as such we can ignore the pitch of the character.

Once we have these data, we can utilize the spherical coordinate system. You probably know the cartesian coordinate system with fixed axis X, Y, Z. Any given object is placed in the coordinate system by its coordinates relative to a point (0, 0, 0) , e.g. (1000, 1001, 30).
In spherical coordinate system we also define points with three parameters. In this case we ask for the distance or radius to a given point (0, 0, 0) as well as the horizontal angle (heading) and vertical angle (pitch). We can easily calculate missing data in one coordinate system if we know the data in the other system. If you don’t know about spherical coordinates I really recommend checking it out.

Here I’m going to skip the mathematical explanation and will rather just comment out a few lines of the resulting code. Note that the function name isn’t necessarily correct. Rather than getting the looking vector itself you are getting a second point on the vector, implying you know the first one as the camera coordinates themselves.

You give your player ped as well as a radius (how far to look for another ped, e.g. 30 (metres) ).

-- returns the vector in which direction the player is looking (middle of the screen). Works first and third person
-- only use this for the local player, not other players' peds
-- usage: Vector3 = GetPlayerLookingVector(GetPlayerPed(-1), INT)
function GetPlayerLookingVector(playerped, radius)
	local pedyaw = GetEntityHeading(playerped)
	local camyaw = GetGameplayCamRelativeHeading()
	local pitch = 90.0-GetGameplayCamRelativePitch()
	local yaw = pedyaw + camyaw -- entity heading + relative camera heading = absolute camera heading

    -- this is a crude way to make sure that the heading is between -180° and 180°. This is necessary for the mathematical functions following
	if yaw > 180 then
		yaw = yaw - 360
	elseif yaw < -180 then
		yaw = yaw + 360
	end

    -- the transformation from spherical coordinates to cartesian coordinates as taken from wikipedia.
    -- note that there is an important difference in x and y.
    -- reason is that in mathematics the angle 0° is defined by looking into positive x direction.
    -- in GTA V the angle 0° has your character facing north, thus in positive y direction.
    -- the transformation has to respect this fact.
	local pitch = pitch * math.pi / 180
	local yaw = yaw * math.pi / 180
	local x = radius * math.sin(pitch) * math.sin(yaw)
	local y = radius * math.sin(pitch) * math.cos(yaw)
	local z = radius * math.cos(pitch)

    -- the following code calculates the second coordinate which is then returned.
    -- note the minus in the correction for x.
    -- The above transformation didn't properly respect the different definition of the angle making the minus necessary.
	local playerpedcoords = GetGameplayCamCoord()
	local xcorr = -x+ playerpedcoords.x
	local ycorr = y+ playerpedcoords.y
	local zcorr = z+ playerpedcoords.z
	local Vector = vector3(tonumber(xcorr), tonumber(ycorr), tonumber(zcorr))
	return Vector
end

Now that we have the second point nothing stops us from putting everything together. I don’t know how much coding experience you have but I’m certain that you can do that without me pasting my solution :stuck_out_tongue:

If you have any questions or can’t work it out feel free to answer, I’ll surely check out how you are progressing.

1 Like

Answering to a DM I got.

print(GetPlayerLookingVector(playerPed, 50))
print(GetPedInDirection(GetGameplayCamCoord(), GetPlayerLookingVector(playerPed, 50)))

the issue here is that playerPed isn’t defined. Put a playerPed = GetPlayerPed(-1) in front of your code.

The ped is defined in other rows. This is not the problem… Any tip?

Paste the whole source code please

playerPed is from the core part of the script the return the current player ped

Citizen.CreateThread(function ()
  while true do
    print(GetPlayerLookingVector(playerPed, 50))
    print(GetPedInDirection(GetGameplayCamCoord(), GetPlayerLookingVector(playerPed, 50)))

    Citizen.Wait(0)
  end
end)

The code is working. It’s just the camera needs to look at a ped which you don’t do currently.
Copy the following code as a test:

	local texturedict = "srange_gen"
	local texturename = "medaldot_32"
	local ButtonPressed = false
	RequestStreamedTextureDict(texturedict, true)

	CreateThread(function()
		while true do
			if IsControlJustPressed(0, 170) then
				ButtonPressed = not ButtonPressed
			end
			Wait(0)
		end
	end)

	CreateThread(function()
		while true do
			while ButtonPressed do
				DrawSprite(texturedict, texturename, 0.5, 0.5, 0.009, 0.0165, 0.0, 0, 0, 0, 190)
				DrawSprite(texturedict, texturename, 0.5, 0.5, 0.007, 0.013, 0.0, 255, 255, 255, 190)
				Wait(0)
			end
			Wait(10)
		end
	end)

Press F3 to bring up a “crosshair” or a point in the middle of the screen. Put that point over the ped and the functions should work.

Just tested. Same result.

function GetPedInDirection(coordFrom, coordTo)
	local rayHandle = StartShapeTestRay(coordFrom.x, coordFrom.y, coordFrom.z, coordTo.x, coordTo.y, coordTo.z, 4, GetPlayerPed(-1), 0)
	local _,flag_PedHit,PedCoords,_,PedHit = GetShapeTestResult(rayHandle)
	return flag_PedHit, PedCoords, PedHit
end

function GetPlayerLookingVector(playerped, radius)
	local pedyaw = GetEntityHeading(playerped)
	local camyaw = GetGameplayCamRelativeHeading()
	local pitch = 90.0-GetGameplayCamRelativePitch()
	local yaw = pedyaw + camyaw -- entity heading + relative camera heading = absolute camera heading

    -- this is a crude way to make sure that the heading is between -180° and 180°. This is necessary for the mathematical functions following
	if yaw > 180 then
		yaw = yaw - 360
	elseif yaw < -180 then
		yaw = yaw + 360
	end

    -- the transformation from spherical coordinates to cartesian coordinates as taken from wikipedia.
    -- note that there is an important difference in x and y.
    -- reason is that in mathematics the angle 0° is defined by looking into positive x direction.
    -- in GTA V the angle 0° has your character facing north, thus in positive y direction.
    -- the transformation has to respect this fact.
	local pitch = pitch * math.pi / 180
	local yaw = yaw * math.pi / 180
	local x = radius * math.sin(pitch) * math.sin(yaw)
	local y = radius * math.sin(pitch) * math.cos(yaw)
	local z = radius * math.cos(pitch)

    -- the following code calculates the second coordinate which is then returned.
    -- note the minus in the correction for x.
    -- The above transformation didn't properly respect the different definition of the angle making the minus necessary.
	local playerpedcoords = GetGameplayCamCoord()
	local xcorr = -x+ playerpedcoords.x
	local ycorr = y+ playerpedcoords.y
	local zcorr = z+ playerpedcoords.z
	local Vector = vector3(tonumber(xcorr), tonumber(ycorr), tonumber(zcorr))
	return Vector
end

local texturedict = "srange_gen"
local texturename = "medaldot_32"
local ButtonPressed = false
RequestStreamedTextureDict(texturedict, true)

CreateThread(function()
  while true do
    if IsControlJustPressed(0, 170) then
      ButtonPressed = not ButtonPressed
    end
    Wait(0)
  end
end)

CreateThread(function()
  while true do
    while ButtonPressed do
      DrawSprite(texturedict, texturename, 0.5, 0.5, 0.009, 0.0165, 0.0, 0, 0, 0, 190)
      DrawSprite(texturedict, texturename, 0.5, 0.5, 0.007, 0.013, 0.0, 255, 255, 255, 190)
      Wait(0)
    end
    Wait(10)
  end
end)

Citizen.CreateThread(function ()
  while true do
    print(GetPlayerLookingVector(playerPed, 50))
    print(GetPedInDirection(GetGameplayCamCoord(), GetPlayerLookingVector(playerPed, 50)))

    Citizen.Wait(0)
  end
end)```

playerPed is not defined. You need to put in playerPed = GetPlayerPed(-1) in that file.

1 Like

I finally get why the code didn’t work.

I the script I’ve made for the creating of peds i put

SetEntityCollision(ped, false, true)

That doesn’t interact with StartShapeTestRay
After removing the line the code works well.