How would you see if a player is facing a model?

If I wanted all player to have a ray through their head would I do this?

-- serverscript
game.Players.PlayerAdded:Connect(function(plr) 
local character = plr.CharacterAdded:Wait()
local origin = Character.Head

local Raycast = Ray.new(origin, Head.CFrame.LookVector*500)
local hit, position = FindPartOnRayWithIgnoreList(Raycast, Character:GetDescendants())

if (hit and hit.Parent and hit.Parent:IsA("Model") then
    print(hit.Parent.Name)
else
    print("No model found")
end
end)
1 Like

error: 09:30:04.357 - ServerScriptService.Script:8: Expected ‘)’ (to close ‘(’ at column 4), got ‘then’

That script will fire a Ray when a player joins, but It will only fire once. The best thing you can do is using RunService.RenderStepped into a LocalScript at the Character

game:GetService("RunService").RenderStepped:Connect(function()
    --// Put the code here
end)

Instead of this right? (30 chars)

error: 09:34:37.579 - Players.Kamlkaze_Kid.Backpack.LocalScript:8: Expected ‘)’ (to close ‘(’ at column 4), got ‘then’

1 Like

even when I did that error showed up, how do I fix that?

Do this in a local script:

(UNTESTED CODE)

local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()

local Range = 500

game:GetService("RunService").RenderStepped:Connect(function()

local ray = Ray.new(Character.Head.Position, Character.Head.CFrame.LookVector * Range)
local hit = workspace:FindPartOnRay(ray)

if hit then

local model = hit.Parent or hit.Parent.Parent

if model and model:IsA("Model") then
print(model.Name)
  end

 end
end)
1 Like

Actually, has it is a LocalScript, you could directly put it into StarterCharacterScripts and use script.Parent, being sure that it will always find the character without creating infinite yields.

1 Like

Using the dot product would also be a good way to do this, if you’d like to see this method I could also write some code for it.

There is a very good tutorial in youtube about Dot Product made by @okeanskiy

Check it out here https://www.youtube.com/watch?v=BUwAcW_18Ws

This is an example of using the dot product to calculate if the player is looking at a specific object:

local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()

local Range = 500

--initializing functions--

local vector3 = Vector3.new 
local dot = vector3().Dot
----------------------

local ModelName = "Chair" 

local Chair = workspace[ModelName]

game:GetService("RunService").RenderStepped:Connect(function()
	
	local ChairLookVector = Chair.PrimaryPart.CFrame.LookVector
	local Unit = (Character.HumanoidRootPart.Position - Chair.PrimaryPart.Position).Unit
	
	local dotProduct = dot(ChairLookVector, Unit)

	if dotProduct >= (0.9) or dotProduct <= (-0.9) then
		print("Looking at chair")
	end

end)

I don’t understand why people are recommending Raycasting in a thread where the OP specifically requested that solutions do not require Raycasting.

The best solution for your problem (most likely) is Dot product, which can be called on a Vector3 value in a script or command bar. In this case, it will return a value defined by the variable dot, which is used as a metric to determine if a object is facing its target.

local threshhold = 0 --set this number to the 'percent' at which the object is facing the target (-1 for fully facing away, 1 for completely facing the target); values go for all real numbers between -1 and 1

function ObjIsLookingAtTarget(object,target) --make sure all arguments passed in this function have a CFrame value
    local dot = (object.CFrame.LookVector:Dot(target.Position-object.Position).Unit) -- computes the dot product between the object and target
    print(dot>=threshhold) -- is the object facing the target?
    return dot >= threshhold -- will return a true or false value for later usage
end

Hope this helped!

1 Like

So this will tell if the player is facing the model or not?

Yes. If you are using a model, make sure that you are sending the Model.PrimaryPart as an argument, and not the entire model. The PrimaryPart of the model can be set using Model:SetPrimaryPart() or manually in the in-studio explorer.

For best accuracy, make sure the PrimaryPart is near or exactly at the center of the model.

Error: 13:15:29.889 - Players.Kamlkaze_Kid.Backpack.LocalScript:19: attempt to index nil with ‘HumanoidRootPart’

Nothing printed, and there were no errors, also, were do I define the model?

Do this

local RP = Character:WaitForChild("HumanoidRootPart")

and then replace

local Unit = (Character.HumanoidRootPart.Position - Chair.PrimaryPart.Position).Unit

with this:

local Unit = (RP.Position - Chair.PrimaryPart.Position).Unit

This?

local RP = Character:WaitForChild("HumanoidRootPart")
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()

local Range = 500

--initializing functions--

local vector3 = Vector3.new 
local dot = vector3().Dot
----------------------

local ModelName = "Chair" 

local Chair = workspace[ModelName]

game:GetService("RunService").RenderStepped:Connect(function()
	
	local ChairLookVector = Chair.PrimaryPart.CFrame.LookVector
	local Unit = (RP.Position - Chair.PrimaryPart.Position).Unit
	
	local dotProduct = dot(ChairLookVector, Unit)

	if dotProduct >= (0.9) or dotProduct <= (-0.9) then
		print("Looking at chair")
	end

end)
1 Like

even though the player is not looking at the chair, it is printing

The dot product method checks if the player is in range of the chair, if you want to make it so the player is directly looking at the chair you should use the raycasting method.

How do you do that though…