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.
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
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
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)
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?
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
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.
I get the Neck Instance from the function above
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
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.)