How to make arms follow cursor with Gun tool

How would I go about making the arms follow the cursor’s Y axis? I’ve already achieved the first person aspect of the issue, I just need the arms to follow when the cursor goes up and down.

3 Likes

I would suggest getting the arm shoulder joints and using trig to get the angle.

Firstly, you’ll have to get the vector from the joint to the mouse. To find the joint position you can just use an offset of the torso or upper torso (eg. torso.CFrame*CFrame.new(0,1,3)).

Let’s call the vector from the torso to the mouse “mv”, and the joint position what you came up with based on the paragraph above.

local mv = mouse.Hit.p-jointPosition

Now, to find the angle of it, we will need to manipulate it a bit. At the moment it is broken up into x, y, and z components. We will have to take the x and z components, and use the Pythagorean Theorem to create a single triangle in 3D space.

cl will be the length that the mouse stretches out.

local cl = math.pow(mv.X^2+mv.Z^2,0.5)

We now have enough information to get the angle. If pt is the angle in radians,

local pt = math.atan2(mv.Y,cl)

You can then set the C0 angle of the joint to CFrame.Angles(pt,0,0). You’ll also have to multiply it by a CFrame offset specific to the joint you’re changing, which can be easily found through trial and error as I do not have it memorized. If you’re in a lazy mood here’s an outline of the math required for the script.

local mv = mouse.Hit.p-jointPosition
local cl = math.pow(mv.X^2+mv.Z^2,0.5)
local pt = math.atan2(mv.Y,cl)

10 Likes
local angle = math.acos((mouse.Origin.p - mouse.Hit.p).unit.y)
local X, Y, Z = Torso["Right Shoulder"].C0:ToEulerAnglesXYZ
Torso["Right Shoulder"].C0 = CFrame.new(Torso["Right Shoulder"].C0.Position) * CFrame.Angles(angle, Y, Z)
X, Y, Z = Torso["Left Shoulder"].C0:ToEulerAnglesXYZ()
Torso["Left Shoulder"].C0 = CFrame.new(Torso["Left Shoulder"].C0.Position) * CFrame.Angles(angle, Y, Z)
1 Like

That will rotate infinitely if I’m not mistaken, did you mean C0.p when referencing the old value?

No it won’t. It rewrites the existing CFrame using the old values. I’ve done this many times before. Trust me, it works.

Also, when I was writing that I meant to use the Position attribute in the C0, that’s probably where you got that from.

Well I have a pretty basic idea and it works just fine. I tested it out on studio just a few moments ago.

First off you would need to define the default C0 values of whichever shoulder is holding the weapon. After, do the same for the gun’s motor6D.

After manipulating both of the arms, simply do

ToolMotor.C0 = Rshoulder.C0:ToWorldSpace(CFrame.new(.15, 0, 0))

I just put a random offset in the parameter, you are going to have to modify that until it fits your desire. You can learn more about CFrames here:

As for manipulating the arms, I suppose you can get the mouse.Hit.Position, and if the Y position of the target is bigger then let’s say 20 studs, then you could clamp the Y position to 20 so the players’ arm does not go as high.

Same goes for the X position, you can clamp it that way as well. I’m going for such a cheap solution here not because I dislike trigonometry, don’t get me wrong that’s literally my field in math, but to not get too complicated and to not use too much CPU power in the process of using trigonometric functions.

local RightShoulder = Character.Torso["Right Shoulder"]
local LeftShoulder = Character.Torso["Left Shoulder"]

local Target = mouse.Hit.Position

local Y = Target.Y
local X = Target.X
local Z = Target.Z

Y = math.clamp(Y, -1,20)
X = math.clamp(X, -10,10)

local constructedVector = Vector3.new(X,Y,Z)

Rightshoulder.C0 = Rightshoulder.C0:Lerp(CFrame.lookAt(defaultRightShoulderC0, constructedVector), 0.1)
Leftshoulder.C0 = Rightshoulder.C0:Lerp(CFrame.lookAt(defaultLeftShoulderC0, constructedVector), 0.1)
ToolMotor.C0 = Rshoulder.C0:ToWorldSpace(CFrame.new(.15, 0, 0))

Again though, you would have to record the default C0 values of the motors, otherwise the CFrame value would keep on multiplying until your limbs reach Saturn.

Sorry for being so late on the concept, I did not realise this post was dated back to 2019. Still though, give it a try if you’re still struggling with it(I’d doubt)

The thing about that part is that the default C0 values are cframes however CFrame.lookAt() requires vector 3. What can I do?