Since the arms worked normally and the head was rotating the exact opposite way, the rotation of the head must be inverted in order to get it to rotate correctly.
Copy the value of the CameraOrientation variable and then delete that variable line. Create two variables instead of the CameraOrientation variable, one called CameraHeadOrientation and CameraArmOrientation.
The CameraArmOrientation property should be set to the value of CameraOrientation and the CameraHeadOrientation should be the same, except where the .7 is at near the end of the function call, you want to make it negative.
Making the .7 negative essentially inverts the orientation. The function multiplies the inverse cosine (which is the angle of rotation in radians) calculated in your function by the tween argument, so if you inverse the tween argument and multiply that by the inverse cosine, the inverse cosine angle will essentially be inverted, as opposed to the arm angle.
What you do then is replace CameraOrientation for the neck, right shoulder and left shoulder's C0. CameraHeadOrientation should be the replacement for CameraOrientation in the Neck's C0 and CameraArmOrientation should be the replacement for CameraOrientation in the remaining left and right shoulder C0s.
Your final script will now look like this:
003 | local InputService = game:GetService( "UserInputService" ) |
004 | local Camera = game.Workspace.CurrentCamera |
005 | local Player = game.Players.LocalPlayer |
006 | local Character = Player.Character |
007 | local Head = Character.Head |
008 | local Torso = Character.Torso |
009 | local RootPart = Character.HumanoidRootPart |
010 | local RootJoint = RootPart.RootJoint |
012 | local RightShoulder = Torso:WaitForChild( "Right Shoulder" ) |
013 | local LeftShoulder = Torso:WaitForChild( "Left Shoulder" ) |
015 | Camera.CameraType = "Scriptable" |
016 | InputService.MouseBehavior = Enum.MouseBehavior.LockCenter |
022 | local components = cf().components |
023 | local inverse = cf().inverse |
024 | local fromAxisAngle = CFrame.fromAxisAngle |
025 | local atan,atan 2 = math.atan,math.atan 2 |
028 | local function toAxisAngleFromVector(v) |
030 | return z*z< 0.99999 and v 3 (v.y,-v.x, 0 ).unit*acos(-z) or v 3 () |
033 | local function AxisAngleLookOrientation(c,v,t) |
035 | local rv = (inverse(c)*v).unit |
037 | return rz*rz< 0.99999 and c*fromAxisAngle(v 3 (rv.y,-rv.x, 0 ),acos(-rz)*(t or 1 )) or c |
040 | local function AxisAngleLookNew(v,t) |
043 | return rz*rz< 0.99999 and fromAxisAngle(v 3 (rv.y,-rv.x, 0 ),acos(-rz)*(t or 1 )) or cf() |
046 | local function AxisAngleLook(c,v,t) |
047 | local rv = (inverse(c)*v).unit |
049 | return rz*rz< 0.99999 and c*fromAxisAngle(v 3 (rv.y,-rv.x, 0 ),acos(-rz)*(t or 1 )) or c |
055 | local Sensitivity = 0.005 |
058 | local CameraDirection = Vector 3. new( 0 , 0 , 1 ) |
060 | local function EulerAnglesYX(l) |
062 | return atan(l.y/(x*x+z*z)^ 0.5 ),-atan 2 (x,-z) |
065 | local function AnglesXY(l) |
067 | return atan 2 (l.y,-z),-atan 2 (l.x,-z) |
070 | local function MouseMoved(Input) |
071 | if Input.UserInputType = = Enum.UserInputType.MouseMovement then |
072 | local dx,dy = Input.Delta.x*Sensitivity,Input.Delta.y*Sensitivity |
075 | CameraDirection = (AxisAngleLookOrientation(RootPart.CFrame,CameraDirection)*fromAxisAngle(v 3 (-dy,-dx, 0 ),m 2 ^ 0.5 )).lookVector |
077 | local RootOrientation = RootPart.CFrame-RootPart.Position |
078 | local RelativeDirection = RootOrientation:inverse()*CameraDirection |
079 | local AngX,AngY = AnglesXY(RelativeDirection) |
080 | if AngX<- 1.57 * 11 / 12 then |
081 | local y,z,c,s = RelativeDirection.y,RelativeDirection.z,math.cos(- 1.57 * 11 / 12 -AngX),-math.sin(- 1.57 * 11 / 12 -AngX) |
083 | CameraDirection = RootOrientation*v 3 (RelativeDirection.x< 0 and -( 1 -y*y-z*z)^ 0.5 or ( 1 -y*y-z*z)^ 0.5 ,y,z) |
084 | elseif AngX> 1.57 * 11 / 12 then |
085 | local y,z,c,s = RelativeDirection.y,RelativeDirection.z,math.cos( 1.57 * 11 / 12 -AngX),-math.sin( 1.57 * 11 / 12 -AngX) |
087 | CameraDirection = RootOrientation*v 3 (RelativeDirection.x< 0 and -( 1 -y*y-z*z)^ 0.5 or ( 1 -y*y-z*z)^ 0.5 ,y,z) |
092 | local Mouse = Player:GetMouse() |
096 | Mouse.KeyDown:connect( function (k) |
104 | InputService.InputChanged:connect(MouseMoved) |
110 | local DirectionBound = 3.14159 / 3 |
113 | local function CameraUpdate() |
114 | Camera.CameraType = "Scriptable" |
115 | local cx,cz = CameraDirection.x,CameraDirection.z |
116 | local rvx,rvz = RootPart.Velocity.x,RootPart.Velocity.z |
117 | if rvx*rvx+rvz*rvz> 4 and cx*rvx+cz*rvz<- 0.5 *(cx*cx+cz*cz)^ 0.5 *(rvx*rvx+rvz*rvz)^ 0.5 then |
118 | DirectionBound = math.min(DirectionBound* 0.9 ,math.abs(CurrentAngY* 0.9 )) |
120 | DirectionBound = DirectionBound* 0.1 + 3.14159 / 3 * 0.9 |
122 | local AngX,AngY = EulerAnglesYX((RootPart.CFrame-RootPart.Position):inverse()*CameraDirection) |
124 | RootPart.CFrame = RootPart.CFrame*CFrame.Angles( 0 ,AngY-. 01 , 0 ) |
125 | elseif AngY<-. 01 then |
126 | RootPart.CFrame = RootPart.CFrame*CFrame.Angles( 0 ,AngY+. 01 , 0 ) |
128 | _,CurrentAngY = EulerAnglesYX((RootPart.CFrame-RootPart.Position):inverse()*CameraDirection) |
129 | local CameraHeadOrientation = AxisAngleLookNew((RootPart.CFrame-RootPart.Position):inverse()*CameraDirection,-. 7 ) |
130 | local CameraArmOrientation = AxisAngleLookNew((RootPart.CFrame-RootPart.Position):inverse()*CameraDirection,. 7 ) |
131 | Neck.C 0 = CFrame.new( 0 , 1 , 0 , - 1 , - 0 , - 0 , 0 , 0 , 1 , 0 , 1 , 0 )*CameraHeadOrientation* CFrame.Angles( 0 , 0 , 0 ) |
132 | RightShoulder.C 0 = CFrame.new( 1 ,. 5 , 0 )*CameraArmOrientation* CFrame.Angles( 0 , math.pi / 2 , 0 ) |
133 | LeftShoulder.C 0 = CFrame.new(- 1 ,. 5 , 0 )*CameraArmOrientation* CFrame.Angles( 0 , math.pi / - 2 , 0 ) |
134 | local PreCam = AxisAngleLook(RootPart.CFrame*cf( 0 , 1 , 0 ),RootPart.CFrame*v 3 ( 0 , 1 , 0 )+CameraDirection)*CFrame.new( 3 , 0.825 , 0 ) |
135 | local Part,Position = workspace:findPartOnRay(Ray.new(PreCam.p,PreCam.lookVector*- 5 ),Character) |
136 | Camera.CoordinateFrame = PreCam*CFrame.new( 0 , 0 ,(Position-PreCam.p).magnitude) |
140 | game:GetService( "RunService" ).RenderStepped:connect(CameraUpdate) |
There may be a more efficient way to do this, but this is what I could come up with that worked for me.
I hope my answer helped you. If it did, be sure to accept it.