Player's character's normals inverting

i’m using this local script for the player so he will face the same direction the camera looks (like using shift lock), and the player can press a button to freely move his camera, but it appears that sometimes when the player changes camera modes, the character’s normals invert. I know this is caused by an invalid rotation matrix, but i’m using the camera’s rotation matrix on the player, and for some reason sometimes the camera has a negative rotation matrix, causing this to happen:

also, if i grab the absolute value of every element of the rotation matrix, the camera just doesn’t work properly
btw here is the code i’m using:

		local humanoid = character:WaitForChild("Humanoid")
		local rootPart = character:WaitForChild("HumanoidRootPart")		

		local cameraAngleX = 7.5
		local cameraAngleY = 0

		local function playerInput(actionName, inputState, inputObject)
			if _G.laserActive == true then
				if inputState == Enum.UserInputState.Change then
					cameraAngleX = cameraAngleX - inputObject.Delta.X
					cameraAngleY = math.clamp(cameraAngleY-inputObject.Delta.Y*0.4, -75, 75)
					rootPart.CFrame = rootPart.CFrame * CFrame.Angles(0, math.rad(-inputObject.Delta.X), 0)
		ContextActionService:BindAction("PlayerInput", playerInput, false, Enum.UserInputType.MouseMovement, Enum.UserInputType.Touch)

		if _G.laserActive2 == true and _G.delay == false then
			humanoid.AutoRotate = false			
			if camera.CameraType ~= Enum.CameraType.Scriptable then
				camera.CameraType = Enum.CameraType.Scriptable
			local startCFrame = * CFrame.Angles(0, math.rad(cameraAngleX), 0) * CFrame.Angles(math.rad(cameraAngleY), 0, 0)
			local cameraCFrame = startCFrame:ToWorldSpace(, cameraOffset.Y, cameraOffset.Z))
			local cameraFocus = startCFrame:ToWorldSpace(, cameraOffset.Y, -10000))
			camera.CFrame =, cameraFocus.Position)
			local xVector = camera.CFrame.XVector *,1,1)
			rootPart.CFrame  = rootPart.CFrame:Lerp(CFrame.fromMatrix(rootPart.CFrame.Position,camera.CFrame.XVector, rootPart.CFrame.YVector, rootPart.CFrame.ZVector),1) 
		elseif _G.laserActive2 == false and _G.delay == false then
			if camera.CameraType ~= Enum.CameraType.Track then
				camera.CameraType = Enum.CameraType.Track
			humanoid.AutoRotate = true
			local startCFrame = * CFrame.Angles(0, math.rad(cameraAngleX), 0) * CFrame.Angles(math.rad(cameraAngleY), 0, 0)
		elseif _G.delay == true then
			if camera.CameraType ~= Enum.CameraType.Attach then
				camera.CameraType = Enum.CameraType.Attach
			humanoid.AutoRotate = false


The problem with your code is that you are using the camera’s rotation matrix directly on your player. However, this rotation matrix can be negative, which will cause the character’s normals to invert.

To fix this, you should use a combination of the camera’s rotation matrix and the player’s current rotation matrix. This can be done by multiplying the two rotation matrices together, which will create a new rotation matrix that will represent the combined rotation of the camera and the player.

You can then use this new rotation matrix on the player to make sure that the player’s normals are always facing the same direction as the camera.

You should also avoid taking the absolute value of each element of the rotation matrix, as this will cause the camera to not work properly.

i’m sorry, i didn’t understand this well. how would i multiply them? could you give me an example of how the code might look like? im kinda new to coding sorry

from what i’ve tried so far, only thing i got was the character spinning like crazy

nevermind i got it, what i did was instead of multiplying the rotation matrixes, i just added up the vector3 for the XVector of the camera’s cframe and the player’s cframe
What i did in case someone else in the future has this problem:

rootPart.CFrame  = rootPart.CFrame:Lerp(CFrame.fromMatrix(rootPart.CFrame.Position,(camera.CFrame.XVector + rootPart.CFrame.XVector), rootPart.CFrame.YVector, rootPart.CFrame.ZVector),1)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.