How would I detect if a part is infront or behind the player?

I want to be able to detect if a part is infront or behind the player, as i’ve made a part-detecting script which basically finds the closest part to the player.
The script also detects parts behind the player, which I don’t want.

	local Position_Contain = {}
	for Index,Child in pairs(Model:GetChildren()) do
		table.insert(Position_Contain,Index,(Child.Position - Core.Position).Magnitude)
	end
	for Index,Child in pairs(Model:GetChildren()) do
		if (Core.Position - Child.Position).Magnitude == math.min(unpack(Position_Contain)) then
				print(Child)

help appreciated :slight_smile:

4 Likes

You can use Raycast for detecting if a part is infront of the player, then filter out the player’s character so it doesn’t consider the character a valid result

1 Like

not gonna lie, i’ve tried to learn raycasting and it’s super confusing. do you have a video i could use by any chance? i feel like the dev forum overcomplicates alot of things

1 Like
local function IsPartBehind(Character: Model, Part)
	local hrp = Character:FindFirstChild("HumanoidRootPart")
	if hrp then
		return math.acos(hrp.CFrame.LookVector:Dot((Part.Position-hrp.Position).Unit)) > math.pi/2
	end
end

Just pass the Character and the Part you will check.

5 Likes

could you explain

math.acos

to me please?

1 Like

I tested this code out and while it does return true if the player’s character is in front of the part,
it would return false sometimes if
The player was in front of the part and also facing the part’s front
And also return true if the player’c character was directly behind the part but facing the complete opposite of the part’s lookvector

1 Like

math.acos is the inverse function of cosine. If you dont know what cosine is, there are many videos about it. Anyways, what it does (in my code) is take the angle of the Dot product between the two vectors.

1 Like

thats the problem, i dont want it to detect parts behind.

1 Like

You can use the solution from a similar post

1 Like

ok, i’ve tried that code out, i’ve edited it slightly to be compatible with my code.
its not detecting any part for some reason anymore, im pretty sure its returning false. here’s my new code.

function GetDistanceFromChildren()
if canSwing == true then
local Position_Contain = {}
for Index,Child in pairs(Model:GetChildren()) do
table.insert(Position_Contain,Index,(Child.Position - Core.Position).Magnitude)
end
for Index,Child in pairs(Model:GetChildren()) do
if (Core.Position - Child.Position).Magnitude == math.min(unpack(Position_Contain)) then
print(Child)

  			if Core then
  				return math.acos(Core.CFrame.LookVector:Dot((Child.Position-Core.Position).Unit)) > math.pi/2
  			end
1 Like

Well, thats technically infront of the player, thus the “IsBehindPlayer” returns false.

Facing away from the part means you put the part behind you. And my code does check if it is behind you.

2 Likes

What is Core? Is that the HumanoidRootPart?

Note: My code returns true if it is behind the player. If you want it to return false instead, use this.

return math.acos(Core.CFrame.LookVector:Dot((Child.Position-Core.Position).Unit)) < math.pi/2
1 Like

Core is the HumanoidRootPart, yes.

I’m not much of an advanced scripter, so I dont really understand this, could I have help putting this into my script to make it work please? Or help understanding how this really works. I’m horrible at math to be honest.

also, with this script i dont get any errors but it still doesn’t work.

sorry if im being a pain rn

Ok, let’s debug this. Debugging is the process of finding the error. Change your “IsBehind” code to this

if Core then
	local angle = math.acos(Core.CFrame.LookVector:Dot((Child.Position-Core.Position).Unit))
	print(angle/math.pi*180) -- Turn into degrees
	return angle < math.pi/2
end

Can you tell me what it prints. Then can you send a screenshot of you and the part you are checking.

it prints correctly. it prints the angle im facing

Well, if it prints properly then you should be good with this.

local isInfront = false
if Core then
	local angle = math.acos(Core.CFrame.LookVector:Dot((Child.Position-Core.Position).Unit))
	isInfront = angle < math.pi/2
	if isInfront then
		-- Do something if it's infront
	else
		-- Do something if it's behind
	end
end

-- You can also access it outside the if statement
if isInfront then
	-- Do something if it's infront
else
	-- Do something if it's behind
end
1 Like

that works now, thanks alot, have a good day

1 Like

by any chance would there be a way to make it so that it searches again for the closest object that IS infront of the player? and to make it so that it can still print objects next to the player?

If you aren’t too worried about performance, and have a specific radius in mind, there are new tricks to determine line of sight:

WorldRoot (roblox.com)

GetPartBoundsInRadius: This will get you all parts within X of the player.
GetPartBoundsInBox: If you whitelist the parts from the radius test and look at the box in front of the player, the result is all parts in front of the player within X.

well my pc is kinda a literal potato, so thats not rlly gonna work