I’m trying to make a system where upon equipping a tool, such as a gun or melee, the character’s real arms are hidden and a pair of fake, viewmodel arms is CFramed to the character. This is so the arms can point up and down with the mouse/camera.
local cam = workspace.CurrentCamera
local viewmodel = cam.Viewmodel
local vmHum = viewmodel.Humanoid
local vmPart = viewmodel.PrimaryPart
game:GetService("RunService").RenderStepped:Connect(function(dt)
local mousePos = mouse.Hit.Position
local X = -(math.asin((char.HumanoidRootPart.Position - mousePos).unit.y))
vmPart.CFrame = char.Head.CFrame * CFrame.Angles(X,0,0)
end)
Note:
The viewmodel is basically an R6 character with all the parts invisible except the arms. The PrimaryPart in this case is the head.
Result:
Fake arms - viewmodel being rotated
As you can see in the above video, it works but the arms sort of move away from the shoulder as they’re rotating; I want to negate this offset so that it stays in position like the real arms, similar to the video below:
Real arms - Motor6Ds being rotated
You may be wondering, why don’t I just rotate the Motor6Ds of the real arms to achieve this?
Well, I tried this in my previous gun systems, and it works, but with a catch: tools have to be welded to the Right or Left Arm, otherwise they don’t rotate with the arms properly.
This means the arm that the tool is welded to can’t be animated, as it’s in a fixed position relative to the tool - for example, a bolt action rifle welded to the Right Arm can’t have any animations of the right arm pulling the bolt back, making for some pretty scuffed animations.
Using fake arms allows me to weld tools to the Torso or HumanoidRootPart of the viewmodel, while maintaining the smooth up and down movement with the mouse, as the whole viewmodel can be rotated instead of having to edit motor6Ds. This gives me much more freedom in animating.
Here is an idea of what you can do to get this offset.
The issue is the pivot center is the head CFrame which the arms are welded at a constant position C0 away from as you mentioned.
You can get the world position relative to 0,0,0 origin of the arm joints using the Motor6D formula
(Part0.CFrame * C0).Position
This is the target constraint relative to the torso.
So it’s just about adjusting the viewmodel welds which starts relative to the head to go to that position.
local motor = script.Parent
local target = workspace.Target
local function worldCFrameRotationToC0ObjectSpace(motor6DJoint,worldCFrame)
local part1CF = motor6DJoint.Part1.CFrame
local part0 = motor6DJoint.Part0
local c1Store = motor6DJoint.C1
local c0Store = motor6DJoint.C0
local relativeToPart0 = part0.CFrame:inverse() * worldCFrame * c1Store
local goalC0CFrame = relativeToPart0
return goalC0CFrame
end
while true do
task.wait()
motor.C0 = worldCFrameRotationToC0ObjectSpace(motor, target.CFrame)
end
That wouldn’t work though as I’d have to weld tools to the arms so they would follow the rotation of the arm joint properly. The whole point I’m using fake arms for this is so I can rotate the arms without editing the shoulder joints; this lets me weld a tool to the Torso of the viewmodel and it will follow the rotation of the arms, as the whole viewmodel assembly including the tool is rotated.
My problem now is just making the viewmodel pivot from the shoulders instead of the head (the head is the PrimaryPart):
Red is the viewmodel, blue is the real character
Would something like ToObjectSpace work for this? Or would I just manually offset it by a factor of X, for example: