Fps arms (beam based) spinning weirdly

i did some fps script and i tried doing the arms beam based like a raycast beam
they worked well but theres 1 problem, they spinning weirdly when i move the camera on the X or Y axis

how its supposed to look:

how it looks when i move my camera up,down,left or right:

heres some part of the code:

local distance = (Camera.CFrame.p - handle.CFrame.p).Magnitude
local cameraoffset = (Camera.CFrame * larm_offset)

larm.Size = Vector3.new(.5,.5,distance)
–larm.CFrame = (Camera.CFrame * larm_offset)
larm.CFrame = CFrame.new(cameraoffset.p, handle.CFrame.p) * CFrame.new(0, 0 , -distance/2)

heres the module script:

local module = {}

module.Offset = CFrame.new(0.5,-0.8,-1.3) * CFrame.Angles(0,-190,0)
module.larm_offset = CFrame.new(1,-1,0)

return module

plz help

I believe the cause is this issue with CFrame.new

CFrame.new is unstable according to the documentation.

At high pitch angles (around 82 degrees), you may experience numerical instability. If this is an issue, or if you require a different up vector, it’s recommended you use CFrame.fromMatrix instead to more accurately construct the CFrame. Additionally, if lookAt is directly above pos (pitch angle of 90 degrees) the up vector switches to the X-axis.

The solution should be to replace it with the newer CFrame.lookAt which as mentioned has a safety mechanism for the high pitch angles scenario.

i tested it and its still spinning

code changed:

local cameraoffset = (Camera.CFrame * larm_offset)
local distance = (cameraoffset.p - handle.CFrame.p).Magnitude

larm.Size = Vector3.new(.5,.5,distance)
--larm.CFrame = (Camera.CFrame * larm_offset)
larm.CFrame = CFrame.lookAt(cameraoffset.p, handle.CFrame.p) * CFrame.new(0, 0 , -distance/2)

its still with the spinning problem its making me crazy cuz i never managed to make a fps framework succefully its infinite+1 hard for some reason

edit:

i tried doing some tests and i think this is caused due to the distance:

is there a way to make a cframe only spin on the axis i want?

arm code:

local cameraoffset = (Camera.CFrame * larm_offset)
local distance = (cameraoffset.p - handle.CFrame.p).Magnitude

larm.Size = Vector3.new(.5,.5,distance)
larm.CFrame = CFrame.lookAt(cameraoffset.p, handle.CFrame.p) * CFrame.new(0, 0 , -distance/2)

module:

local module = {}

module.Offset = CFrame.new(0.5,-0.8,-1.3) * CFrame.Angles(0,-190,0)
module.larm_offset = CFrame.new(1,-1,0)

return module

Ok, so I believe the problem stems from the CFrame methods being used is relative to the world, where we need it to be relative to the CFrame. I suggest learning most of the CFrame constructors and multiplication in order to have more tools at your disposable when solving a CFrame based problem like this.

For now, I will suggest a CFrame.fromMatrix method that uses the camera’s up vector in order to make it relative to the camera and not to the world like CFrame.lookAt which makes the arms point “up” in the direction of Vector3.new(0,1,0)

local cameraPosition = cameraoffset.Position
local lookVector = handle.CFrame.p-cameraoffset.p
local upVector = Camera.CFrame.UpVector
local newRightVector = lookVector:Cross(upVector)
 
larm.CFrame = CFrame.fromMatrix(cameraPosition,newRightVector,upVector)* CFrame.new(0, 0 , -distance/2)

it worked thx