How do I make it so my NPC tries to get out of player FOV?

Basically, whenever dot product is > .3 then I want it to try to get out of it before dot product is > .55
Does anyone know what I can do to start my script off? I know a little bit about pathfinding alr

What I have so far:

``
local npc = game.workspace:WaitForChild(“Dummy”)
local character = script.Parent

local HideEvent = workspace.Hide
local EscapeEvent = workspace.Escape

while task.wait() do
local npcToCharacter = (npc.Head.Position - character.Head.Position).Unit
local npcLook = character.Head.CFrame.LookVector

local dotProduct = npcToCharacter:Dot(npcLook)

if dotProduct > .3 and dotProduct < 0.55 then
	--- When being looked at
	HideEvent:Fire()
	workspace.Baseplate.Color = Color3.new(1, 0.52549, 0.52549)
elseif dotProduct > .55 then
	EscapeEvent:Fire()
	workspace.Baseplate.Color = Color3.new(1, 0, 0)
else
	npc.AI.Enabled = true
	workspace.Baseplate.Color = Color3.new(0.631373, 1, 0.54902)
end

end
``

1 Like

There’s probably a few ways you could do this, without knowing the exact needs and what variables need to be accounted for (i.e. are we first person? third person? is there a difference in Y coordinates between user and AI?) its hard to think up a reliable system.

Here’s an outline of how I’d start, although I suspect there’s better ways to do so given there’s already a few potential problems to solve with the idea listed below (e.g. looking upwards and all edges of the screen are pointing to the sky)

  1. Dot products meet necessary values

  2. Determine the necessary point that is off screen to move the AI to

  3. Ok, so, we have:
    Point A (You the player’s position);
    Point B (The NPC’s position)
    Point C (Where off screen to move the humanoid).
    That’s three points - a triangle - Trig has entered the chat.

  4. Convert Point B to a Vector2/UDim2 via Camera:WorldToScreenPoint to get the X and Y values

  5. Logically speaking, the edge of your screen, with respect to the 2D coordinates of the model would be represented by UDim2.new(1,0,0,Y_Coord_In_Pixels).
    Note: You can convert the X_Coordinate from pixels to scale by diving X_Coordinate by the X value of the screen resolution and if the value is less than 0.5 then make it default to a scale of 0 (the left side of the screen) or if greater than 0.5 then 1 (the right side of the screen)

  6. Convert that 2D coordinate to a 3D coordinate using Camera:ScreenPointToRay which will return the 3D Position of where the ray hits- ideally this is off screen , but you can recast a new ray.

    Alternatively, you may try using (Camera.FieldOfView/2)+1 to possibly get the Y-Degrees needed to cast a Ray towards a point that is just offscreen.

  7. Humanoid:MoveTo(Spot) or Use Pathfinding if its not a simple/linear path

2 Likes

I’m confused on step 5, how would I use UDim2.new()?

UDim2 holds four values: {X_Scale, X_Offset, Y_Scale, Y_Offset}

The scale values are a measure of what “percentage” of the respective Axis to cross. In simple terms:

  • 0 = 0% (Left screen border for X, Top Screen Border for Y)
    UDim2.new(0,0,0,0) would be the top left corner of your screen

  • 1 = 100% (Right screen border for X, Bottom screen border for Y)
    UDim2.new(1,0,1,0) would be the bottom right corner

  • 0.5 = 50% (Halfway across your screen for both X and Y)
    UDim2.new(0.5,0,0.5,0) would be centered

The “Offset” values are measured in Pixels, but the problem with using these without proper accomodations is that Screen Resolution (and thus the number of pixels) varies from devices and therefore players.

In Step 4, Camera:WorldToScreenPoint returns (In Order): A Vector3, and a boolean which is true if the point is visible on screen. The Vector3 thats returned is actually made up of of the X and Y coordinates (In pixels, I.e. the Offset values for the UDim2) and the Z value is the distance between the Player’s Camera and the Vector3 you passed in the Arguments.

Step 5 works to extrapolate this data, and adheres to the idea a 3D point at the edge of your field of view on a horizontal plane would be represented by either a 0 or 1 for the X_Scale value in a UDim2. I substituted the Y position of the AI’s 2D coordinates to try and find a 2D point at the edge of your screen that would be the shortest distance from where the AI is on screen as this would mean you only have to move the shortest necessary distance and is overall less demanding on performance.

1 Like

I’m still confused, is there you could show an example through code if that’s okay?