How to detect if a player is in first person?

Hello everyone,

I have a specific problem that I am trying to figure out. I currently am creating a viewmodel system for my tools. And I can’t figure out how to see if they are in first person or not.

I have tried a few examples like detecting if their cameramode is LockFirstPerson or detecting their first person body transparency.

Here is my script:

--Services
local RunService = game:GetService("RunService")
local ReplicatedFirst = game.ReplicatedFirst

local VIEW_M = ReplicatedFirst.Sword

--Player Junk
local player = game.Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local CurrentCamera = workspace.CurrentCamera

local Tool = script.Parent

Tool.Equipped:Connect(function()
	if player.CameraMinZoomDistance <= 0.5 then
		local VIEW_M_CLONE = VIEW_M:Clone()
		local RUNNING = RunService.RenderStepped:Connect(function() -- Create a function that I can easily disconnect
			if VIEW_M_CLONE then -- If the viewmodel is actually there, do stuff
				print("VIEW_M_CLONE CHECK COMPLETE")
				VIEW_M_CLONE.Parent = workspace
				VIEW_M_CLONE:SetPrimaryPartCFrame(CurrentCamera.CFrame * CFrame.new(0,0,0))
			end
		end)
	end
end)

If you need help understanding, I’m here :^)

3 Likes

Have you tried using the distance between the player’s head and the camera position? i.e. if the distance is less than a certain threshold like <1 you can assume the player is zoomed in?

1 Like

Perhaps, I will test that out. What is it called exactly?

Since you already have a reference to the character and the camera you could use something like:

if (character.Head.Position - CurrentCamera.CFrame.Position).Magnitude < 1 then

Unfortunately, when I tried this out it turns out that the camera doesn’t actually focus on your character’s head but on a point roughly around your head that is anchored to the HumanoidRootPart and it is difficult to figure out the exact position that the camera is supposed to point to, meaning there could be cases where it may think you’re zoomed in when you’re really not.

(Edit: forget all this, as @tlr22 pointed out there is a property of Camera called Focus that I was not aware of at the time I wrote this reply.)

1 Like

This should work

local camera = workspace.CurrentCamera
local distance = (camera.CFrame.p - camera.Focus.p).magnitude 
local isFirstPerson = distance <= 0.75

I grabbed the code from here Camera.FirstPersonTransition
I changed the value to 0.75 instead of 0.5 because it would sometimes be false when in first person

1 Like

Have you tried using Player.CameraMode? Player.CameraMode

1 Like

Yes. Yes I have. It only detects what the camera mode is, not the players fov.

How would I detect this though? I’m confused.

Fov? I thought you were talking about whether their in 1st person or 3rd person?

Yes… Thats what I am talking about. Fov is first person or 3rd person. I need to detect if they are zoomed in ALL the way.

FOV is field of view, it has nothing to do with whether you’re in 1st person or 3rd person.

1 Like

You still get the point. Right?

1 Like

Have you tried looking it up before creating this? I’m sure at least one other person has brought this up.

You would have to loop in order to detect it. Probably every frame. Something like this.

local camera = game.Workspace.CurrentCamera
local isFirstPerson = (camera.CFrame.p - camera.Focus.p).magnitude < 0.75


local function onFirstPersonChanged(val)
	print(val)
end

local detector = function()
	local distance = (camera.CFrame.p - camera.Focus.p).magnitude 
	if distance < 0.75 ~= isFirstPerson then
		isFirstPerson = distance < 0.75
		onFirstPersonChanged(isFirstPerson)
	end
end
game:GetService("RunService"):BindToRenderStep('firstPersonDetector',Enum.RenderPriority.Camera.Value + 1, detector)

Now the onFirstPersonChanged function will fire when first person is entered or exited setting the parameter to true if it’s in first person.

1 Like

How would I fit this into my script? It seems a lot just to put inside my script, and somewhat unnecessary in my opinion.

Ahh. Your script isn’t looking for changes, but rather just if it is in that perspective. My bad. The larger code was to detect changes. Since you only need to know it at time of check you can simply do this.

--Services
local RunService = game:GetService("RunService")
local ReplicatedFirst = game.ReplicatedFirst

local VIEW_M = ReplicatedFirst.Sword

--Player Junk
local player = game.Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local CurrentCamera = workspace.CurrentCamera

local Tool = script.Parent

Tool.Equipped:Connect(function()
    local camera = workspace.CurrentCamera
    local distance = (camera.CFrame.p - camera.Focus.p).magnitude 
    local isFirstPerson = distance <= 0.75 --Now this is equal to true if the character is in first person.  I'm not entirely certain where you want to check?  The next line?
	if isFirstPerson then --This might not be what you want..
		local VIEW_M_CLONE = VIEW_M:Clone()
		local RUNNING = RunService.RenderStepped:Connect(function() -- Create a function that I can easily disconnect
			if VIEW_M_CLONE then -- If the viewmodel is actually there, do stuff
				print("VIEW_M_CLONE CHECK COMPLETE")
				VIEW_M_CLONE.Parent = workspace
				VIEW_M_CLONE:SetPrimaryPartCFrame(CurrentCamera.CFrame * CFrame.new(0,0,0))
			end
		end)
	end
end)
1 Like

Has not seem to do anything quite yet… There’s no errors so the script sees it as a correct statement.

I am not entirely certain where you wanted to check if someone is in first person so I just took a guess. I might have put it in the wrong spot. Keep in mind with what I did it is only checking this once as soon as you equip the tool. You’ll have to loop that check to keep it updated constantly.

Hm, I tried doing a While True Do loop, didn’t do anything. I only want to check when the tool is equipped

How exactly do you want behavior to differ between a state where the character is in first person and a state where the character is not in first person?