Face Camera script doesn't work after player resets?

I have a script that makes the player’s head follow the camera, It works fine when the player first enters but after they’ve reset / died it stops working.

Before dying
https://gyazo.com/863295b5868bfebfc1d330e8c0888035

After dying
https://gyazo.com/d6a5534ec0af63965101e8192c77f254

This is my current code:

function CamHandling:InputUpdate()
	--CAMERA LOOK
	local CameraDirection = Root.CFrame:toObjectSpace(Camera.CFrame).lookVector

	if Neck then
		if Character.Humanoid.RigType == Enum.HumanoidRigType.R15 then
	        Neck.C0 = CFNew(0, YOffset, 0) * CFAng(0, -asin(CameraDirection.x), 0) * CFAng(asin(CameraDirection.y), 0, 0)
		elseif Character.Humanoid.RigType == Enum.HumanoidRigType.R6 then
			Neck.C0 = CFNew(0, YOffset, 0) * CFAng(3 * math.pi/2, 0, math.pi) * CFAng(0, 0, -asin(CameraDirection.x)) * CFAng(-asin(CameraDirection.y), 0, 0)
		end
	end
	
	if Player.Character.Humanoid.Health <= 0 then
		look = false
		Neck.C0 = NeckC0
	end
	
	if look == true then
		game.ReplicatedStorage.Look:FireServer(Neck.C0)
	end
end
2 Likes

Do you set the Character Variable again after the Player respawned? If not, then you are using the old character which has been destroyed to move the head camera.
You can also just put this before the CameraDirection Variable to always have the latest Character, and if there is none don’t even execute the rest.

local Character = game.Players.LocalPlayer.Character
if not Character then return end
1 Like

That didn’t work, it’s not a problem with the old character else the new character wouldn’t be affected at all.

My Variable is

local Character = Player.Character or Player.CharacterAdded:wait()

Could it be by any chance that you are not updating your Neck Variable? Because even if an Instance is destroyed that you have inside a Variable, you can still access its properties.
Can you also tell us where the LocalScript is located at? (StarterGui, StarterPlayer, etc…)

Player.CharacterAdded:Connect(function()
	look = true
end)

function CamHandling:InputUpdate()
	if look == true then
	local Neck = Character:WaitForChild("Head"):WaitForChild("Neck")
	local YOffset = Neck.C0.Y
	--CAMERA LOOK
	local CameraDirection = Root.CFrame:toObjectSpace(Camera.CFrame).lookVector

	if Neck then
		if Character.Humanoid.RigType == Enum.HumanoidRigType.R15 then
	        Neck.C0 = CFNew(0, YOffset, 0) * CFAng(0, -asin(CameraDirection.x), 0) * CFAng(asin(CameraDirection.y), 0, 0)
		elseif Character.Humanoid.RigType == Enum.HumanoidRigType.R6 then
			Neck.C0 = CFNew(0, YOffset, 0) * CFAng(3 * math.pi/2, 0, math.pi) * CFAng(0, 0, -asin(CameraDirection.x)) * CFAng(-asin(CameraDirection.y), 0, 0)
		end
	end
	
	if Player.Character.Humanoid.Health <= 0 then
		look = false
		Neck.C0 = NeckC0
	end
	
	if look == true then
		game.ReplicatedStorage.Look:FireServer(Neck.C0)
	end
	end
end

i’ve changed it to this however it returns with an infinite yield possible error then the neck doesn’t even move anymore.

I have no idea why it doesn’t work for you, I just tried it myself and it works perfectly fine, even after resetting my character. Below is the code I used, it is a bit modified so that the not-existing values are added.

local Player = game.Players.LocalPlayer
local CamHandling = {}
local Character = Player.Character

local look = false
if Character then look = true end

Player.CharacterAdded:Connect(function(NewChar)
	look = true
	Character = NewChar
end)

function CFNew(x,y,z)
	return CFrame.new(x,y,z)
end
function CFAng(x,y,z)
	return CFrame.fromEulerAnglesXYZ(x,y,z)
end
asin = math.asin
local NeckC0 = CFrame.new()

function CamHandling:InputUpdate()
	if look == true then
		local Root = Character.HumanoidRootPart
		local Camera = workspace.CurrentCamera
		
		local Neck = Character:WaitForChild("Head"):WaitForChild("Neck")
		local YOffset = Neck.C0.Y
		--CAMERA LOOK
		local CameraDirection = Root.CFrame:toObjectSpace(Camera.CFrame).lookVector
	
		if Neck then
			if Character.Humanoid.RigType == Enum.HumanoidRigType.R15 then
		        Neck.C0 = CFNew(0, YOffset, 0) * CFAng(0, -asin(CameraDirection.x), 0) * CFAng(asin(CameraDirection.y), 0, 0)
			elseif Character.Humanoid.RigType == Enum.HumanoidRigType.R6 then
				Neck.C0 = CFNew(0, YOffset, 0) * CFAng(3 * math.pi/2, 0, math.pi) * CFAng(0, 0, -asin(CameraDirection.x)) * CFAng(-asin(CameraDirection.y), 0, 0)
			end
		end
		
		if Player.Character.Humanoid.Health <= 0 then
			look = false
			Neck.C0 = NeckC0
		end
		
		if look == true then
			--game.ReplicatedStorage.Look:FireServer(Neck.C0)
		end
	end
end

game:GetService("RunService"):BindToRenderStep("TestCamera", Enum.RenderPriority.Camera.Value, function()
	CamHandling:InputUpdate()
end)

Would forcing shift lock cause this problem?

I’m not getting any troubles either while using Shift Lock, so that can’t be it either. Did you try the above code as stand-alone LocalScript and see if that works?

It appears to be the problem with the Neck, it’s not being found hence the console’s being spammed with infinite yield errors.

Yeah, i tested it out with “FindFirstChild” and neck seems to be nil?

That’s because a R6 Player does not have a Neck Instance inside their Head. When the Player is R6, then you need to get the Neck Instance from the Torso.

Is there a function that allows me to get the Neck instance from the character or do i need to make a function that iterates through all the descendants then return the neck?

This should work, if it ends up erroring just add some sanity checks if the Character exists and all of the children that it accesses within the function.

local function GetNeck(Character)
	if Character:FindFirstChildWhichIsA("Humanoid").RigType == Enum.HumanoidRigType.R15 then
		return Character.Head.Neck
	else
		return Character.Torso.Neck
	end
end

Same problem again, “Neck is not a valid member of part” indicating neck is nil, I’m going to add a repeat wait until neck to see if it works

Still doesn’t work, Neck is still nil?

Try to set the parent of script into starter character scripts and might work :+1:

Try using this modified version:

local function GetNeck(Character)
	if Character:FindFirstChildWhichIsA("Humanoid").RigType == Enum.HumanoidRigType.R15 and Character:FindFirstChild("Head") then
		return Character.Head:FindFirstChild("Neck")
	elseif Character:FindFirstChildWhichIsA("Humanoid").RigType == Enum.HumanoidRigType.R6 and Character:FindFirstChild("Torso") then
		return Character.Torso:FindFirstChild("Neck")
	end
end

The InputUpdate looks like this then for me.

  1. I get the Neck Instance from the function above
  2. Check if Neck is not nil, if it is, don’t execute code below
function CamHandling:InputUpdate()
	if look == true then
		local Root = Character.HumanoidRootPart
		local Camera = workspace.CurrentCamera
		
		local Neck = GetNeck(Character)
		if not Neck then return end
		
		local YOffset = Neck.C0.Y
		--CAMERA LOOK
		local CameraDirection = Root.CFrame:toObjectSpace(Camera.CFrame).lookVector
	
		if Neck then
			if Character.Humanoid.RigType == Enum.HumanoidRigType.R15 then
		        Neck.C0 = CFNew(0, YOffset, 0) * CFAng(0, -asin(CameraDirection.x), 0) * CFAng(asin(CameraDirection.y), 0, 0)
			elseif Character.Humanoid.RigType == Enum.HumanoidRigType.R6 then
				Neck.C0 = CFNew(0, YOffset, 0) * CFAng(3 * math.pi/2, 0, math.pi) * CFAng(0, 0, -asin(CameraDirection.x)) * CFAng(-asin(CameraDirection.y), 0, 0)
			end
		end
		
		if Player.Character.Humanoid.Health <= 0 then
			look = false
			Neck.C0 = NeckC0
		end
		
		if look == true then
			--game.ReplicatedStorage.Look:FireServer(Neck.C0)
		end
	end
end

That didn’t work, just did the same thing, not sure why it would have.

@SimplyData i’ll try your method out in a second let me just move the scripts back into playerscripts

Tecnically if your script is in starter character scripts it should reset everytime character respawn

It didn’t work, again same thing. it’s saying that GetNeck returns nil

Did you add

if not Neck then return end

after you retrieved the Neck? And are you supplying the Character as argument to the function? If possible, can you post the updated code you have now?

Player.CharacterAdded:Connect(function(char)
	look = true
	repeat wait() until char.Head.Neck
end)

function CamHandling:InputUpdate()
	if look == true then
		local Neck = GetNeck(Character)
		if not Neck then return end
		
		local YOffset = Neck.C0.Y
		
		--CAMERA LOOK
		
		local CameraDirection = Root.CFrame:toObjectSpace(Camera.CFrame).lookVector
	
		if Neck then
			if Character.Humanoid.RigType == Enum.HumanoidRigType.R15 then
		        Neck.C0 = CFNew(0, YOffset, 0) * CFAng(0, -asin(CameraDirection.x), 0) * CFAng(asin(CameraDirection.y), 0, 0)
			elseif Character.Humanoid.RigType == Enum.HumanoidRigType.R6 then
				Neck.C0 = CFNew(0, YOffset, 0) * CFAng(3 * math.pi/2, 0, math.pi) * CFAng(0, 0, -asin(CameraDirection.x)) * CFAng(-asin(CameraDirection.y), 0, 0)
			end
		end
		
		if Player.Character.Humanoid.Health <= 0 then
			look = false
			Neck.C0 = NeckC0
		end
		
		if look == true then
			game.ReplicatedStorage.Look:FireServer(Neck.C0)
		end
	end
end

I’ve added what you’ve suggested
The error:

20:43:39.802 - Neck is not a valid member of Part
20:43:39.804 - Stack Begin
20:43:39.804 - Script 'Players.InternallyAmplified.PlayerScripts.Control.CamHandler', Line 25 - upvalue GetNeck
20:43:39.805 - Script 'Players.InternallyAmplified.PlayerScripts.Control.CamHandler', Line 38 - method InputUpdate
20:43:39.806 - Script 'Players.InternallyAmplified.PlayerScripts.Control', Line 42
20:43:39.806 - Stack End

(Adding the “FindFirstChild” still doesn’t help, it just removes the errors being displayed.)