I’m currently trying to created a target system where if the player is looking at an enemy, they will attack the enemy. The enemy will be surrounded by others so I plan to get the position of where the player is looking and find the nearest enemy to attack. How would I go about getting the position of where the player is looking?
What defines the position of where the player is looking? their root part? their mouse position?
Their camera defines the position, I’m thinking about using the LookVector of the camera and then passing this info to the server but I don’t know how I would find the nearest enemy. I was thinking about using a for loop that loops through the workspace and finds the lowest distance between an enemy and a player’s camera lookvector but then I don’t exactly know how I would find the lowest distance.
There are many threads on how to calculate the closest entity:
do what @Synteuro does and also factor in dot product as well so you can’t attack something directly behind you
This video explains dot product well
This worked well in finding the nearest enemy but I ran into a problem. Almost every single time I print the camera’s lookvector’s magnitude, it always comes back with 1. It’s like the magnitude never changes, which of course leads to problems. Is there anyway to fix this?
Do you mean you want to calculate the closest entity that’s also within the field of view of the player?
Kinda, I want the camera to also be leaning towards the enemy. What I’m trying to do is find the position where the player’s camera is looking, then find the nearest enemy based on the camera position.
Do you mean something like this?
The decided part is based off of a combination of the closest part (position wise) and where the camera is currently facing.
The LookVector always has a magnitude of 1 because it is a Unit Vector
that is relative (direction) to your RootPart’s CFrame. This functionality is correct. You can obtain a position that is actually in front of the character by doing something like this:
local root = char.PrimaryPart
local lookVector = root.CFrame.LookVector
local range = 5 -- measured in studs
local direction = root.Position + lookVector * range
If you want a position right in front of a part, you can make the range 1.
You can do this with the Camera
object as well, as you wanted I believe.
Not exactly what I had in mind but I think that would work great, how did you achieve this?
It’s a bit complicated, but here is the premise:
Within a LocalScript, I have a table that stores a reference to all of the parts I want to keep track of. In this case, the 4 color parts are referenced in the table. Then, within a RenderStepped event, I create a local table which is used to store any of those 4 parts that are within the camera’s field of vision. I achieve this by utilizing some CFrame mechanics which is shown on line 20 of the code (see below). Note that I can change the field of view to my liking. Next, I loop through the table of parts within the field of vision, and find the closest part based on magnitude. Finally, I update the GUI with the determined part.
Here’s the code:
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local parts = {}
parts.GreenPart = workspace:WaitForChild("GreenPart")
parts.YellowPart = workspace:WaitForChild("YellowPart")
parts.RedPart = workspace:WaitForChild("RedPart")
parts.BluePart = workspace:WaitForChild("BluePart")
local label = script.Parent:WaitForChild("BestEntity")
local player = Players.LocalPlayer
local camera = workspace.CurrentCamera
local angle = camera.FieldOfView
RunService.RenderStepped:Connect(function()
local partsInVision = {}
for _, part in pairs (parts) do
if math.pow((camera.CFrame.LookVector-(part.CFrame.p-camera.CFrame.p).Unit).Magnitude/2,2) < angle/360 then
table.insert(partsInVision, part)
end
end
local closestPart = nil
local closestDistance = nil
for _, part in pairs (partsInVision) do
if not closestPart then
closestPart = part
closestDistance = (part.CFrame.p-camera.CFrame.p).Magnitude
continue
end
if (part.CFrame.p-camera.CFrame.p).Magnitude < closestDistance then
closestPart = part
closestDistance = (part.CFrame.p-camera.CFrame.p).Magnitude
end
end
if closestPart then
label.Text = closestPart.Name
label.TextColor3 = closestPart.Color
else
label.Text = "No part"
label.TextColor3 = Color3.new(0,0,0)
end
end)
It’s a bit of a mess. If you have any further questions, feel free to add me on Discord @jamston#1608. I will respond to you there.
You could just raycast from the character’s humanoid root part’s lookvector.
local run = game:GetService("RunService")
local players = game:GetService("Players")
local player = players.LocalPlayer
local camera = workspace.CurrentCamera
local enemies = workspace:WaitForChild("Enemies") --Enemy folder.
run.RenderStepped:Connect(function()
local visibleEnemies = {}
for _, enemy in ipairs(enemies:GetChildren()) do
local position, visible = camera:WorldToScreenPoint(enemy.PrimaryPart.Position)
if visible then
table.insert(visibleEnemies, enemy)
end
end
if #visibleEnemies > 0 then
local closestEnemy, closestDistance = nil, math.huge
for _, visibleEnemy in ipairs(visibleEnemies) do
local distance = player:DistanceFromCharacter(visibleEnemy.PrimaryPart.Position)
if distance < closestDistance then
closestEnemy = visibleEnemy
closestDistance = distance
end
end
if closestEnemy then
--Decide what to do with closest visible enemy.
end
end
end)
So I decided to write a script following your example. To explain how it works it collects a group of enemies which are currently within the camera’s view, following this the distance between the player’s character and each visible enemy is calculated in order to determine the enemy closest to the player’s character.