I want to have the characters head match the Up/Down and Left/Right rotation of the camera while being clamped to facing forwards ( e.g. you look backwards the head rotates forwards like with the example code bellow ). I currently have the following code but it doesn’t work when the character turns to any other direction then straight:
local Plr = game:GetService( "Players" ).LocalPlayer
game:GetService( "RunService" ).RenderStepped:Connect( function ( )
local Neck = Plr.Character and Plr.Character:FindFirstChild( "Torso" ) and Plr.Character.Torso:FindFirstChild( "Neck" )
if Neck then
local Y, X, Z = workspace.CurrentCamera.CFrame:toEulerAnglesYXZ( )
Y = -Y - math.rad( 90 )
if X > 0 and X < 1.57 then
X = X + ( 1.57 - X ) * 2
elseif X < 0 and X > -1.57 then
X = X + ( -1.57 - X ) * 2
end
Neck.C0 = CFrame.new( 0, 1, 0 ) * CFrame.Angles( X, Y, Z )
end
end )
I’m currently playing around with your code, but while you wait you should take into account the fact that this will not work with R15 character rigs, which are becoming more and more prominent than R6 as time goes by.
Instead you can retrieve the neck in Character.Head.Neck, which can just be cross-compatible with the following code:
local CFNew, CFAng = CFrame.new, CFrame.Angles
local asin = math.asin
local Camera = workspace.CurrentCamera
local Player = game.Players.LocalPlayer
repeat wait() until Player.Character
local Character = Player.Character
local Root = Character:WaitForChild("HumanoidRootPart")
local Neck = Character:FindFirstChild("Neck", true)
local YOffset = Neck.C0.Y
game:GetService("RunService").RenderStepped:Connect(function()
local CameraDirection = Root.CFrame:toObjectSpace(Camera.CFrame).lookVector.unit
if Neck then
Neck.C0 = CFNew(0, YOffset, 0) * CFAng(0, -asin(CameraDirection.x), 0) * CFAng(asin(CameraDirection.y), 0, 0)
end
end)
FYI that won’t work if they die or get a new character, here’s the fixed code for anyone wondering (Plus some optimisations and a check to make sure the camera is focused on the player):
local CFNew, CFAng, CFtoObjectSpace = CFrame.new, CFrame.Angles, CFrame.new( ).toObjectSpace
local asin, pi, hpi = math.asin, math.pi, math.pi / 2
local Plr= game.Players.LocalPlayer
game:GetService("RunService").RenderStepped:Connect(function()
if Plr.Character then
local Root, Neck, Humanoid, Camera = Plr.Character:FindFirstChild("HumanoidRootPart"), Plr.Character:FindFirstChild("Neck", true), Plr.Character:FindFirstChild("Humanoid"), workspace.CurrentCamera
if Root and Neck and Humanoid and Camera.CameraSubject then
local R6 = Humanoid.RigType == Enum.HumanoidRigType.R6
if Camera.CameraSubject.Parent == Plr.Character then
local CameraDirection = CFtoObjectSpace(Root.CFrame, Camera.CFrame).lookVector.unit
Neck.C0 = CFNew(Neck.C0.p) * CFAng(0, -asin(CameraDirection.x), 0) * (R6 and CFAng(-hpi + asin(CameraDirection.y), 0, pi) or CFAng(asin(CameraDirection.y), 0, 0))
else
Neck.C0 = R6 and CFNew(Neck.C0.p) * CFAng(-hpi, 0, pi) or CFNew(Neck.C0.p)
end
end
end
end)
Well since it’s already been necrobumped, forgive me for chiming in. Clients have network ownership over their character, my approach is to use this and rotate a part based on the camera’s orientation that will replicate over to the server. From this part’s orientation the server can handle the rotating without remote traffic. It still counts towards the 50KB/s and still has the latency associated with replicating. Works well enough for me though.
I’ve had several likes on this post over the past few weeks so I thought I’d provide a more up to date implementation of this that I’m using. This version replicates to other clients at a configurable rate (defaults to every 1/20 of a second, I found this to be sufficient) and uses a fake head so that collisions/physics aren’t affected by the rotation.
You just need the HeadRotation script in ServerScriptService and the HeadRotation localscript in StarterPlayer.StarterPlayerScripts
Can I also use this for rotation the character to the position of the camera? This is for a gliding system and I will be changing the neck to the humanoid root part.
You can also do head cloning just incase the player having headless, I encountered this problem a bit ago and fixed it by using a Server script checking if the neck is found, if not (Headless usually doesn’t have a neck) then it will create a new one by Cloning the old once and using the same property’s as the old head by making it transparent and such.