How do I make it so my 3rd Person R15 Character holds a gun correctly at all camera angles along a semi circular line that doesn't curve along other axis (Motor6D's/CFrames)?

I currently have a custom R15 Character that I’m using for an FPS game.
Nothing fancy, just a basic character.
I know Motor6d manipulation, however in order for the arms to go along a semi circular path that doesn’t curve along other axis, they bend inwards, which doesn’t make any sense to me. I’m wondering if anyone with good CFrame knowledge can help me with this, ordering the CFrames correctly.
This is the character currently, however the arms have an unnatural bend in them, which is what I want to fix.
image
image
As you can see, the arm is bending inwards when it should infact be straight and not curved. This is a behaviour also observed in the other arm, however is not as noticeable.
The arms do follow along the desired path I want them to go along however (Semi circular no curve)
image
image
(This is the arms mapped out with parts at different angles)
I need to make it so the arms do not have this weird angle problem which is happening.
My current script:

local players = game:GetService("Players")
local runService = game:GetService("RunService")
local plr = players.LocalPlayer
local camera = workspace.CurrentCamera
local chr = plr.Character
if not chr or not chr.Parent then chr = plr.CharacterAdded:Wait() end
local angle = plr.PlayerGui:WaitForChild("display").angle
wait(1/20)

local ls = chr.LeftUpperArm.LeftShoulder
local le = chr.LeftLowerArm.LeftElbow
local rs = chr.RightUpperArm.RightShoulder
local re = chr.RightLowerArm.RightElbow
local root = chr.LowerTorso.Root
local neck = chr.Head.Neck

local ltc0 = root.C0
local hc0 = neck.C0

local luac0 = ls.C0
local llac0 = le.C0
local ruac0 = rs.C0
local rlac0 = re.C0

local rad, deg = math.rad, math.deg
local ang = CFrame.Angles

local camrot = 0
local rx1 = 40
local rx2 = -20

local charrot = 0

root.C0 = ltc0 * ang(0, rad(-charrot), 0)
neck.C0 = hc0 * ang(0, rad(charrot), 0)

local function armupdate()
	ls.C0 = luac0 * ang(rad(70), 0, 0) * ang(camrot, 0, 0) * ang(0, 0, rad(rx1))
	le.C0 = llac0 * ang(rad(30), 0, 0)
	rs.C0 = ruac0 * ang(rad(20), 0, 0) * ang(camrot, 0, 0) * ang(0, 0, rad(rx2))
	re.C0 = rlac0 * ang(rad(120), 0, 0)
end

armupdate()

local rla = chr.RightLowerArm
local lla = chr.LeftLowerArm

local function newpart(x, r)
	local part = Instance.new("Part")
	part.Size = Vector3.new(0.5, 0.5, 0.5)--10)
	part.Anchored = true
	part.CanCollide = false
	part.CFrame = x.CFrame * CFrame.new(0, -x.Size.Y/2, 0)
	part.Parent = workspace
	return part
end

part = newpart(rla, rx1)
part2 = newpart(lla, rx2)

local function update()
	armupdate()
	local partclone = part:Clone()
	partclone.Parent = workspace
	local part2clone = part2:Clone()
	part2clone.Parent = workspace
	part.CFrame = rla.CFrame * CFrame.new(0, -rla.Size.Y/2, 0)
	part2.CFrame = lla.CFrame * CFrame.new(0, -lla.Size.Y/2, 0)
end

angle.FocusLost:Connect(function()
	if angle.Text ~= "" then
		if tonumber(angle.Text) then
			camrot = rad(tonumber(angle.Text))
		else
			angle.Text = "0"
			camrot = 0
			
		end
	else
		angle.Text = "0"
		camrot = 0
	end
	update()
end)

I’m aware the code may be a little messy, this is only a test!, however I have a feeling I have done something wrong with how I have ordered the rotations of the CFrames.
Here is the place I am working on (so you can download):
https://drive.google.com/open?id=1E41zGBlQUYFJ1oSu662-Xra-RllFUxvJ
I would appreaciate any help I can get on this, its been annoying me quite a bit I can’t seem to figure this out.

3 Likes